aooy/blog

aoy的说明书

aooy opened this issue · 6 comments

aooy commented

作者:杨敬卓

转载请注明出处

目录

  • 前言
  • 动机
  • 原理
  • 使用
  • 总结

前言

随着移动端的崛起,现代标准浏览器的推广,为解决浏览器兼容问题的jQuery渐渐没落。vue和react这些新的前端框架带来了完全不一样的开发体验,不再需要手动去处理dom节点,只需要关心数据层面的问题。

动机

流行的框架和库往往因为功能齐全导致体积巨大,有时我们只用到它们很少的功能,尝试去学习原理,自己实现特定功能有益于学习。

aoy深受Vue和react的影响,是使用Vue和react后,去实践写的一个简单框架。在Vue和react中,每个组件都可以有自己的数据存储容器,当父子组件或不同层级组件需要频繁大量的通信数据时,如果没有Vuex和redux这些状态管理框架,往往最后会变得一团糟。

把所有组件的数据存储在一个唯一的容器里,数据只在容器和组件之间流动。 这是aoy的设计理念。现在aoy只有最基本的功能。只有600行代码,想了解Virtual DOM和diff算法的同学可以试着去阅读源码。

原理

使用了Object.defineProperty绑定store的数据,当观察到数据改变,比较新旧数据产生的Virtual DOM,将差异应用到真实dom上。练练ps,给大家画张图。

使用

//初始化aoy实例,取得store
var aoy = Aoy.init();
var store = aoy.store;
var el = aoy.el;

//数据
var userData = [
	{name: 'c', age: 19, city: 'Beijin'},
	{name: 'a', age: 20, city: 'Xian'},
	{name: 'b', age: 12, city: 'Hangzhou'},
	{name: 'd', age: 30, city: 'Wuhan'}
];

//将数据添加进store
store.add('table',{
	userData: userData
});

//封装的节点函数,便于复用
function Table(childern){
	return el('table',childern);
}

function Tr(childern){
	return el('tr', childern);
}
function Th(txt){
	return el('td', txt);
}
function Td(txt){
	return el('td', txt);
}

//记录字段的排序
var sortStore = Object.create(null);

//创建组件
var mytable = aoy.createComponent({
	el: document.body,
	sortData: function(field,e){  //字段的排序函数
		let i;
		userData.sort(function(a, b){
			if(i = (sortStore[field] === 'down')){		
				if(a[field] < b[field]) return 1;
			}else{
				if(a[field] > b[field]) return 1;
			}
		});
		sortStore[field] = i?'up':'down';
		this.table.userData = userData;
	},
	render: function(){
		var trs = [
				el('tr',[
						 el('th',{onclick: this.sortData.bind(this, 'name') },'name'), 
						 el('th',{onclick: this.sortData.bind(this, 'age') },'age'), 
						 el('th',{onclick: this.sortData.bind(this, 'city') },'city')
						]
					)
				];
		this.table.userData.forEach(function(v, i){
				var tdName = Td(v.name);
				var tdAge = Td(v.age);
				var tdCity = Td(v.city);
				var tr = Tr([tdName, tdAge, tdCity]);
				trs.push(tr);
			});	
		var table = Table(trs);
		return table;
	}
});
// 连接组件与数据,同时渲染进文档
aoy.connect(mytable,'table');
  • 如果想最大化的利用dom节点,例如 ul > li *n 结构,可以给节点加上key属性。
var userData = [
	{name: 'c', key: '3'},
	{name: 'a', key: '1'},
	{name: 'b', key: '2'},
	{name: 'd', key: '4'}
];
function Li (v) {
   return el('li',{ key :  v.key}, v.name);
}
var list = [];
userData.forEach(function ( v ){
  list.push( Li(v) );
})
function render () {
  return el('ul',[ list ]);
}

Note

  • 只在需要大量重绘的地方使用。

  • 每个aoy实例都会初始化自己的store, 建议一个document下只实例化一个aoy。

  • 在组件中使用this时,this均指向它的调用者。如果需要在调用时取得组件,可以使用bind绑定。

var myinput = aoy.createComponent({
	el: document.body,
	inputFn: function(){
		console(this)      //input
	},
	render: function(){
		return el('Input', {oninput: this.inputFn,type: 'text' });
	}
});
var myinputComponent= aoy.createComponent({
	el: document.body,
	inputFn: function(){
		console(this)      //myinputComponent
	},
	render: function(){
		return el('Input', {oninput: this.inputFn.bind(this),type: 'text' });
	}
});
  • 依赖计算只绑定到最高层级, 也就是shore的key,当你修改shore的一个深层对象时,视图不会有反应。aoy并没有像vue那样为组件所调用的每一个数据做依赖计算,甚至覆盖数组的原生方法达到双向绑定的目的。这意味着优化的钥匙掌握在使用者手中,可以将深层次的数据结构拆分,也可以搭配immutable-js使用。
var aoy = Aoy.init()
var store = aoy.store
store.add('a' , {b: {text: 'this is p' }})
var myP = aoy.createComponent({
	el: document.body,
	render: function(){
		return el('p',this.a.b.text);
	}
});
aoy.connect(myP, 'a')
aoy.store.get('a').b.text = 'new'  //视图不会改变
aoy.store.get('a').b ={text: 'new'} //视图更新

总结

aoy可以说是学习Vue和react原理再结合自己想法的产物,还有很多不足之处。

大神,膜拜一下,打算通读一下源码

带我一个,我也要通读一下源码

上个车

明天有时间看一下源码,我是实习生,哈哈加油

谢谢大神的项目!已通读源码,深有体会 =)
react和vue源码过于复杂,您的项目极大得帮助了像我这样想要了解web framework架构的学生
然后弱弱提一点,"shore"是个typo吧?

谢谢大神的项目!已通读源码,深有体会 =)
react和vue源码过于复杂,您的项目极大得帮助了像我这样想要了解web framework架构的学生
然后弱弱提一点,"shore"是个typo吧?

应该是笔误 store