vue 框架是对js html 的封装
在框架设计中,需要权衡设计
在范式上,视图的显示通常分为两个命令式和声明式
比如更新一个内容
1 2 3 4 5 6
| const div = document.querySelector('#app')
div.innertText = 'hello world'
div.addEventListener('click',()=>{alert('ok')})
|
像一个命令一样,先获得元素,再改变元素
将还有一种是声明式
1
| <div @click='()=> alert('ok')> hello world </div>
|
通过声明html模版来绑定数据,实现的结果,通过框架来实现
有一点像sql 语句
只需要输入一段sql语句,至于sql 编译器如何得到想要的数据,什么磁盘读取,不用关心
因为输入的是声明,sql编译器会不断的帮我们进行优化,这也是vue会在写前端进行帮助,会帮助优化。
但是由于声明式会被翻译成命令式,在vue内部,即使帮助优化,但是声明式的性能不会由于命令式代码的性能
在某种程度上,声明式最好的性能就是最少必要修改的命令式
所以vue这种框架的优势不在于性能,而在于可维护性和易用性上
所以说在框架的目的是
在保持可维护性的同时让性能损失最小化
框架使用的虚拟dom
目前常用的框架
vue 或 react 都是使用虚拟dom,为什么使用虚拟dom,为什么不使用dom?
原生dom的操作代价十分巨大,远远超过 js语言所维护的dom
虚拟dom 就是 js所描述的UI,通过虚拟dom,进行UI变化的比较,找到最优的更新方法,就是框架所做的事
运行时 编译时
编译时,写入数据,经过编译成直接运行的
运行时,运行的时候,才能显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const obj = { tag: "div", children: [{ tag: "span", children: "hello world" }], };
function Render(obj, root) { const el = document.createElement(obj.tag); if (typeof obj.chidren === "string") { const text = document.createTreeNode(obj.children); el.appendChild(text); } else if (obj.children) { obj.childern.forEach((child) => Render(child, el)); } root.appendChild(el); }
|
这个代码没有写对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const html = ` <div> <span>hello world</span> </div> ` function Compiler(html){ const tag = html.match(/<\w+>/)[0].slice(1,-1) const text = tag.match(/<\w+>(.*)<\/\w+>/)[1] const children = html.match(/<\w+>(.*)<\/\w+>/)[1] const childrenTag = children.match(/<\w+>/)[0].slice(1,-1) const childrenText = children.match(/<\w+>(.*)<\/\w+>/)[1]
return { tag, children: { tag: childrenTag, children: childrenText } } }
|
输入html这种tag类型,经过编译器的编译,再经过render的渲染,就可以使用来
这就是运行时+编译时
如果直接将内容编译成可以运行的,
这就是编译时
总结
其中命令式更加关注过程,而声明式更加关注结果
声明式的更新性能消耗 = 找出差异的性能消耗 + 直接修改的性能消耗。虚拟DOM 的意义就在于使找出差异的性能消耗最小化。