目录
一、介绍:
二、虚拟节点的属性:
三、如何使用h函数:
四、手写h函数:
1. vnode.js函数:
2. h函数:
h函数是用来产生虚拟节点。
比如这样调用h函数:
h('a',{propr:{href:'https://www.baidu.com/'}},'百度');
将得到这样的虚拟节点:
{"sel":"a","data":{props:{href:"https://www.baidu.com"}},"text":"百度"};
它表示的真正的DOM节点是:
百度
注:从虚拟DOM如何变为真是DOM属于模板引擎(mustache)的内容,而h函数是如何产生虚拟DOM。
{
children:undefined,
data:{},
elm:undefined,
key:undefined,
sel:"div",
text:"我是一个盒子"
}
children:子元素,如果没有子元素就是undefined。
data: 属性值。
elm: 这个元素对应的真正的DOM节点,如果是undefined表示这个虚拟节点还没有上树。
key: 唯一标识。
sel: 表示选择器。
text: 文本内容。
import { init } from 'snabbdom/init'
import { classModule } from 'snabbdom/modules/class'
import { propsModule } from 'snabbdom/modules/props'
import { styleModule } from 'snabbdom/modules/style'
import { eventListenersModule } from 'snabbdom/modules/eventlisteners'
import { h } from 'snabbdom/h' // helper function for creating vnodes
//创建出patch函数
var patch = init([
classModule, // makes it easy to toggle classes
propsModule, // for setting properties on DOM elements
styleModule, // handles styling on elements with support for animations
eventListenersModule, // attaches event listeners
]);
//创建虚拟节点
const myVnode = h('ul',[
h('li',{},'苹果'),
h('li','西瓜'),
h('li',[
h('div',[
h('p','哈哈'),
h('p','嘻嘻')
])
]),
h('li',h('p','火龙果'))
]);
//让虚拟节点上树
var container = document.getElementById('container');
// Second `patch` invocation
patch(container, myVnode);
注:patch函数是diff算法的核心函数,我们下面的博客将会更新讲解patch函数。
注:此方法我们只考虑三个参数的情况:
h('div',{},[]);
h('div',{},文字);
h('div',{},h());
函数的功能很简单:就是把传入的参数组合成对象返回。
//把传入的参数组合成对象返回
export default function(sel,data,children,text,elm){
const key = data.key;
return { sel, data, children, text, elm ,key};
}
注:因为编写的是一个低配版本,所以这个函数必须接受三个参数,缺一不可,相当于它的重载功能较弱。
形态必须是下面的三种之一
形态一: h('div',{},'文字')
形态二:h('div',{},[])
形态三: h('div',{},h())
(1):写出大体框架
import vnode from './vnode'
export default function(sel,data,c){
if(arguments.length != 3){
throw new Error("h函数只能传入3个参数");
}
if(typeof c == 'String' || typeof c == 'number'){
return vnode(sel,data,undefined,c,undefined);
}else if(Array.isArray(c)){
//说明现在调用h函数是形态二
}else if(typeof c == 'object' && c.hasOwnProperty('sel')){
//说明现在调用h函数是形态三
}else{
throw new Error("类型不匹配");
}
};
(2) 写形态二 :数组中嵌套的还是h函数,而h函数执行的结果一定是一个对象。
import vnode from './vnode'
//低配版本h函数 这个函数必须接受三个参数,缺一不可
//相当于它的重载功能较弱
//形态必须是下面的三种之一
/*
h('div',{},'文字')
h('div',{},[])
h('div',{},h())
*/
export default function(sel,data,c){
// 检查参数的个数
if(arguments.length != 3){
throw new Errow("低配版,只能传三个参数");
}
// 检查参数c的类型
if(typeof c === "string" || typeof c === 'number '){
//说明现在调用的是形态一
return vnode(sel,data,undefined,c,undefined);
}else if(Array.isArray(c)){ //形态2
let children = [];
// 遍历c,收集children
for(let i = 0;i
(3)写形态三:因为测试语句中已经执行,我们只需要收集返回即可。
import vnode from './vnode'
//低配版本h函数 这个函数必须接受三个参数,缺一不可
//相当于它的重载功能较弱
//形态必须是下面的三种之一
/*
h('div',{},'文字')
h('div',{},[])
h('div',{},h())
*/
export default function(sel,data,c){
// 检查参数的个数
if(arguments.length != 3){
throw new Errow("低配版,只能传三个参数");
}
// 检查参数c的类型
if(typeof c === "string" || typeof c === 'number '){
//说明现在调用的是形态一
return vnode(sel,data,undefined,c,undefined);
}else if(Array.isArray(c)){ //形态2
let children = [];
// 遍历c,收集children
for(let i = 0;i
注:代码地址。