纯js实现事件驱动视图变化

2020/12/27 功能实现 共 1946 字,约 6 分钟

背景

前段时间看到同事实现了一款简单的ES6模板字符串解析的模板引擎,在公司项目里面也是好几个地方都看到了。于是自己就试着实现他。

实现效果

数据变了,视图跟着变化。简单的效果和vue,react的差不多,但是实现粗糙而已,没有diff 算法,没有虚拟dom对比。 就是简单的整体替换。

在线demo

实现思路

  1. 写一个字符串解析函数
	String.prototype.interpolate = function(params){
		const names = Object.keys(params)
		const vals = Object.values(params)
		const str = new Function(...names,`return \`${this}\`;`)(...vals)
		return str
	}
  1. 可执行的字符串替换模板中的数据
  <template>
    <li id="${id}">${name}</li>
  </template>
  1. 一个数据和视图变化的函数
// 渲染
const render = ()=>{
	[
		{el:foodEle,temp:foodTpl,list:createData.foodList},
		{el:amusementEle,temp:amusementTpl,list:createData.amusementList},
		{el:foodListEle,temp:foodListTpl,list:createData.foodData},
		{el:amusementListEle,temp:amusementListTpl,list:createData.amusementData}
	].forEach(item=>{
		const temp = item.temp?.innerHTML
		if (!temp || !item.el) return;
		item.el.innerHTML = item.list.map(item=>temp.interpolate(item)).join('')
	})
}
// 数据存储,驱动页面变化
const createData = {
	foodList:[],// 自己选择的喜欢的食物
	amusementList:[],// 自己选择的喜欢的娱乐
	foodData:[],// 接口来的数据
	amusementData:[]
}

// 数据响应式变化
const createStore = (state,stateChanger)=>{
	const getState = () => state;
	const listeners = [] // 监听函数
	const subscribe = listener => listeners.push(listener) // 订阅监听函数
	const dispatch = action=>{
		// 执行状态变化函数
		stateChanger(state, action);
		// 所有订阅函数执行
		listeners.forEach(listener => listener());
	}
	return {
		getState,
		dispatch,
		subscribe
	}
}

// 数据变化
const stateChanger = (state,action)=>{
	switch(action.type){
		case "food":
			state.foodList = action.value;
			break;
		case "amusement":
			state.amusementList = action.value;
			break;
		case "foodData":
			state.foodData = action.value;
			break;
		case "amusementData":
			state.amusementData = action.value;
			break;
		default:
			break;
	}
}

// 执行响应式函数
const store = createStore(createData, stateChanger);
store.subscribe(() => render());
  1. 需要变化的时候,执行视图数据变化的视图
    store.dispatch({type,value})
    

简单粗暴吧,仔细看的话,数据驱动视图变化这个在react/vue的框架里面好像见过类似的。只是他们的实现比这个好很多

总结

刚刚开始的时候觉得蛮难的,自己实现下来感觉还不错。同事还实现了一个功能更多的,有时间可以慢慢的学习里面,自己动手实现一下web-template

长路漫漫


在技术的历史长河中,虽然我们素未谋面,却已相识已久,很微妙也很知足。互联网让世界变得更小,你我之间更近。

在逝去的青葱岁月中,虽然我们未曾相遇,却共同经历着一样的情愫。谁的青春不曾迷茫或焦虑亦是无奈,谁不曾年少过

在未来的日子里,让我们共享好的文章,共同学习进步。有不错的文章记得分享给我,我不会写好的文章,所以我只能做一个搬运工

我叫 sunseekers(张敏) ,千千万万个张敏与你同在,18年电子商务专业毕业,毕业后在前端搬砖

如果喜欢我的话,恰巧我也喜欢你的话,让我们手拉手,肩并肩共同前行,相互学习,互相鼓励

文档信息

Search

    Table of Contents