virtual DOM(虚拟节点的实现)
1 利用JS操作真实DOM节点实现页面渲染
- 任务:在一个容器渲染(利用用户信息生成的)表格,再点击按钮进行数据修改,修改后再重新渲染修改后的信息。
- 方式:利用jQuery操作DOM节点,一开始清空容器的内容,再生成表格,渲染表格。
- 弊端:操作DOM很耗费性能,这种方式是直接替换容器中的所有节点,重复的节点无法复用,降低浏览器性能。
- HTML代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="container"></div>
<button id="btn-change">change</button>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<scipt src="domReader.js"></script>
</body>
</html>
const userData = [{
name: '张三',
age: 20,
address: '北京'
}, {
name: '蔡徐坤',
age: 24,
address: '广东'
}, {
name: '蔡明',
age: 26,
address: '河南'
}]
function render(data){
const $container = $('#container');
$container.html('')
var $table = $('<table>')
data.forEach((item,i) => {
if (i===0) {
$table.append(`
<tr>
<td>name</td>
<td>age</td>
<td>address</td>
</tr>
`)
}
$table.append(`
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.address}</td>
</tr>
`)
})
$container.append($table)
}
render(userData)
$('#btn-change').click(() => {
userData[0].name = '谢广坤'
userData[1].age = 30
userData[2].address = '深圳'
render(userData)
})
2 利用snabbdom实现虚拟DOM
- 核心方法:h()、patch()
- h():用于生成虚拟节点树。
-
- 使用方式:
const vnode = h('标签名+id/class', {定义事件}, [存放子节点]或者内容)
- patch(curNode, newNode):传入新旧节点,对比后自动实现替换、修改、移动节点等操作。
const vnode = h('ul#list', { on: { click:handleClick }, [
h('li', {}, 'item1'),
h('li', {}, 'item2'),
h('li', {}, 'item3')
]}
const newNode = h('ul#list', {}, '已清空所有的li')
path(vnode, newNode);
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.min.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/h.js"></script>
<script>
var snabbdom = window.snabbdom;
var patch = snabbdom.init({
snabbdom_class,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
})
var h = snabbdom.h
</script>
<script>
const snabbdom = window.snabbdom;
const patch = snabbdom.init({
snabbdom_class,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
})
const h = snabbdom.h
const userData = [{
name: '张三',
age: 20,
address: '北京'
}, {
name: '蔡徐坤',
age: 24,
address: '广东'
}, {
name: '蔡明',
age: 26,
address: '河南'
}];
userData.unshift({
name: '姓名',
age: '年龄',
address: '地址'
})
function render(data, curNode){
const $table = $("<table>");
const temp = [];
data.forEach((item,i) => {
let trans = h('tr', {}, [
h('td', {}, item.name),
h('td', {}, item.age),
h('td', {}, item.address)
])
temp.push(trans);
})
const newNode = h('table', {}, [...temp])
patch(curNode, newNode)
return newNode
}
let container = $('#container')[0]
let curNode = render(userData, container);
$('#btn-change').on('click', function(){
userData[1].name = '李四'
userData[2].age = 66
userData[3].address = '江西'
newNode = render(userData, curNode)
curNode = newNode
})
</script>
3 整体页面(可用于测试)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="container"></div>
<button id="btn-change">change</button>
</body>
<script src="../node_modules/jquery/dist/jquery.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.min.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/h.js"></script>
<script>
const snabbdom = window.snabbdom;
const patch = snabbdom.init({
snabbdom_class,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
})
const h = snabbdom.h
const userData = [{
name: '张三',
age: 20,
address: '北京'
}, {
name: '蔡徐坤',
age: 24,
address: '广东'
}, {
name: '蔡明',
age: 26,
address: '河南'
}];
userData.unshift({
name: '姓名',
age: '年龄',
address: '地址'
})
function render(data, curNode){
const $table = $("<table>");
const temp = [];
data.forEach((item,i) => {
let trans = h('tr', {}, [
h('td', {}, item.name),
h('td', {}, item.age),
h('td', {}, item.address)
])
temp.push(trans);
})
const newNode = h('table', {}, [...temp])
patch(curNode, newNode)
return newNode
}
let container = $('#container')[0]
let curNode = render(userData, container);
$('#btn-change').on('click', function(){
userData[1].name = '李四'
userData[2].age = 66
userData[3].address = '江西'
newNode = render(userData, curNode)
curNode = newNode
})
</script>
</html>