虚拟dom && diff算法 ( 王者 )
- 虚拟dom是什么?
- 它是一个Object对象模型,用来模拟真实dom节点的结构
- 更少的dom操作会更加减少 时间花费 减少性能损耗
- 例如以下代码
var vdom = { tag: 'div', attr: { className: 'box' }, content: [ { tag: 'ul', content: [ { tag: 'li', content: data.name } ] } ] }
- 虚拟dom的使用基本流程
- 需求: vdom如何模拟真实dom,如果将来我想在div>ul>li标签结构里增加一个li,里的内容为 : 这里是xxxx
在增加10个li,内容为: xxx- 获取数据( ajax fetch )
- 创建虚拟节点
<div class = "box"> <ul> <li> {{ data.name }} </li> </ul> </div>
- 通过render函数解析jsx,将其转换成 vdom结构, 并将vdom渲染成真实dom(render函数)
var vdom = { tag: 'div', attr: { className: 'box' }, content: [ { tag: 'ul', content: [ { tag: 'li', content: data.name } ] } ] }
- 数据更改了, data.name = ‘美女’
data.name = '美女' vdom = { tag: 'div', attr: { className: 'box' }, content: [ { tag: 'ul', content: [ { tag: 'li', content: data.name } ] } ] }
- 使用diff算法比对两次vdom,生成patch对象
- 根据key将patch对象渲染到页面中改变的结构上,而其他没有改变的地方是不做任何修改的( 虚拟dom的惰性原则 )
- 什么是jsx?
- jsx javascript + xml
<div class = "box"> <ul> <li> {{ data.name }} </li> </ul> </div>
- diff算法是什么?
- diff算法是比较两个文件的差异,并将两个文件不同之处,将这个不同之处生成一个补丁对象(patch)
- diff算法来源后端
- 前端将其应用于虚拟dom的diff算法
- vue中将 虚拟dom的diff算法放在了 patch.js文件中
- 使用js来进行两个对象的比较( vdom 对象模型)
- diff算法是同级比较
- 给每一个层级打一个标记,这个标记是一个数字( 这个数字就是 key )
- diff算法运行结束之后,返回什么?
- 补丁对象(patch)
注意: vue是一是MVVM框架,Vue高性能的原因之一就是vdom
深化: Vue vdom vs React vdom 有何不一样?
- 验证 key
- 列表循环一定加key
- key最好是使用具有唯一标识性的 id
- 为什么列表循环要加key ? ( 黄金 )
- key是用来做标识的( 同级比较 )( 比如index做标记的话, 删除这个下标的元素会使得元素样式重复删除那个元素的样式 )
命名:
- 一个单词的大写: 注意不要和原生的h5标签重名,比如 header footer Header Footer
- 小写带- , 比如 header-title
- 大驼峰: ZhangSan 使用 : Zhang-San
Vue有两大特性
-
指令 – 用来操作dom
-
组件 – 组件是html css js 等的一个聚合体
-
为什么要使用组件?
-
组件化
- 将一个具备完整功能的项目的一部分进行多处使用
- 加快项目的进度
- 可以进行项目的复用
-
要想实现组件化,那么我们使用的这一部分就必须是完整的,我们把这个完整的整体就称之为组件
-
插件: index.html img css js
-
如果能将 html css js img 等多个部分放在一起,那该有多好,vue将这个聚合体的文件称之为,单文件组件( xx.vue )
-
-
基础的组件创建
- 全局注册
- Vue.component( 组件的名称,组件的配置项 ) // 配置项和Vue的配置项基本一样
/*<div id="app"> <Father></Father> </div> */ var Hello = Vue.extend({ template: '<div> 这里是father组件 </div>' }) //VueComponent( option ) Vue.component( 'Father', Hello ) //注意顺序(黄金) new Vue({ //这个必须在组件之下 el: '#app' })
- 局部注册
- 在组件中用一个components的配置项目来表示 只能在注册的范围内使用,其他地方是不能使用的
- key: value key是组件名称 value是组件配置项
/*<div id="app"> <zhang-san></zhang-san> </div>*/ var Hello = Vue.extend({ template: '<div> 这里是xx </div>' }) new Vue({ el: '#app', components: { // key: value key是组件名称 value是组件配置项 // 'zhang-san': Hello, 'ZhangSan': Hello } })
- 全局注册
-
必须掌握的
- vue是如何扩展组件的?
- Vue.extend() 是 vue用来扩展 vue功能( 组件 )的
- vue为什么要以标签的形式使用组件
- vue借鉴了react,react中组件是以标签的形式使用的
- 组件使用为何要注册
- 为了符合 html / html5的规则,所以组件的标签化使用必须注册
- vue是如何扩展组件的?
-
组件的一些特殊使用规则 【 is 规则】
-
如上直属父子级如果直接组件以标签化形式使用,那么就会出现bug
- 解决: 使用is规则: 通过is属性来绑定一个组件
<tr is = "Hello"></tr>
- 案例: table
<div id="app"> <table> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> <tr is = "Hello"></tr> </table> </div>
Vue.component('Hello',{ template: '<tr> <td> 4 </td> <td> 2 </td><td> 3 </td></tr>' }) new Vue({ el: '#app' })
- 组件的template
- template使用:
- 实例范围内使用
- template中的内容被当做一个整体了,并且template标签是不会解析到html结构中的
- 实例范围外使用
- 实例范围外template标签是不会被直接解析的
- 组件要想使用template使用,我们采用第二种
- 但是使用第二种template使用后,有个弊端,template标签结构会在html文件中显示
- 解决: 使用webpack、gulp等工具编译,将来要用vue提供的单文件组件
- 实例范围内使用
<div id="app">
<h3> 实例范围内使用 </h3>
<template>
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</template>
<h3> 使用 hello 组件</h3>
<!-- <Hello></Hello> -->
</div>
<h3> 实例范围外使用 </h3>
<template id="hello">
<div>
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
</template>
Vue.component('Hello',{
template: '#hello'
})
new Vue({
el: '#app'
})