操作真实DOM所消耗的时间 和 操作数据所消耗的时间
下面用案例解释
一:
// 操作真实DOM
let count = 0
console.time('b')
var box = document.querySelector( '.box' )
for( var i = 0 ; i <= 10000; i++ ){
count = i
box.innerHTML = count // 这里我就在操作真实dom 10000次
}
console.timeEnd('b')
二:
//操作真实DOM 操作数据
let n = 0 ;
console.time('c')
for ( var i = 0 ; i<= 10000; i++ ){
n = i
}
box.innerHTML = n // 这里操作了一次
console.timeEnd('c')
第二种方法耗时比较小
diff算法
- 这个算法来源于后端,它的作用就是比较两个文件,然后将两个文件中的不同之处挑选出来
- 将挑选出来的内容,形成补丁对象
render 方法 【 渲染函数 】
-
将vdom渲染为真实dom (vdom:虚拟dom)
-
在javascript中书写dom结构,
-
javascript + xml 结合生成了一种新的语法糖: JSX
render () { return ( <div> <ul> <li> 数据 </li> </ul> </div> ) }
-
使用jsx结构模拟vdom,但是vdom是对象模型,必须将jsx 转换 vdom对象模型
-
然后在渲染页面【 真实dom生成 】
下面用例子展示
// 1. 获取数据
var model = {
msg: 'hello '
}
// 2. 创建 VDOM
var vdom = {
tag: 'DIV',
attr: {
className: 'box'
},
children: [
{
tag: 'UL',
attr: {},
children: [
{
tag: 'li',
attr: {},
content: model.msg
}
]
}
]
}
//3. 渲染dom 【 render 】
var box = document.createElement('DIV')
var ul = document.createElement('UL')
var li = document.createElement('LI')
box.className = vdom.attr.className
li.innerHTML = vdom.children[0].children[0].content
ul.appendChild(li)
box.appendChild(ul)
document.body.appendChild( box )
// 4. 数据改变
model.msg = "hello 1905"
// 5. 重新生产vdom [ render ]
vdom = {
tag: 'DIV',
attr: {
className: 'box'
},
children: [
{
tag: 'UL',
attr: {},
children: [
{
tag: 'li',
attr: {},
content: model.msg
}
]
}
]
}
//6. 通过diff算法进行两个vdom的比较,将不同之处挑选出来,形成一个patch对象【 补丁对象 】,再去重新渲染页面
key
key: 作用: 给vdom打标记,实现同层级比较
经验:列表渲染都要加key,key一定是要唯一的标识,最好是id
案例:
<div id="app">
<ul>
<li
v-for = "(item,index) in todos"
:key = "item.id" //此时要用key做唯一标识 如果没有 则删除第一项时 此时列表只剩下一项, 剩下的这一项将变成第一项 也将有未删除前第一项的属性(背景颜色)
>
<p> {{ item.task }} </p>
<div class="btn_box">
<button @click = "modify"> 修改 </button>
<button @click = "remove( index )"> 删除 </button>
</div>
</li>
</ul>
</div>
new Vue({
el: '#app',
data: {
msg: 'hello ',
todos: [
{
id: 1,
task: '任务一'
},
{
id: 2,
task: '任务二'
}
]
},
methods: {
remove ( index ) {
this.todos.splice( index,1 )
},
modify ( e ) {
// 点击修改让整个li的背景颜色为红色
// 以下代码我是用来说明key的作用的,在真实项目中不允许使用
const li = e.target.parentNode.parentNode
li.style.background = 'red'
}
}
})
模拟数据实现方式?
-
为什么要写模拟假数据?
- 前后端分离, 前后端同步开发,接口是没有的
-
mock.js生成 http://mockjs.com/
-
使用经验:
-
安装 npm install mockjs
-
使用的时候找字段结构相近的案例,然后复制语法,然后对应修改
-
// 使用 Mock var Mock = require('mockjs') var fs=require('fs') var data = Mock.mock({ // 属性 list 的值是一个数组,其中含有 4 个元素 'list|4': [{ // 属性 id 是一个自增数,起始值为 1,每次增 1 'id|+1': 1, //name 属性 没次输出一个 'name|1':["qweq","gfd","nbvc","ytre","hgfd"] }] }) // 输出结果 console.log(JSON.stringify(data, null, 4))
-
-
拷贝线上相近的json
- 浏览器开发者工具/ netWork / XHR / copy response
-
easy mock https://easy-mock.com/login
- 生成数据接口
-
- 登录easy mock官网 点击右下角加号 创建接口
数据请求: axios fetch
数据请求的方式
-
原生
-
ajax fetch
-
fetch:
<!-- fetch 是原生js提供的 可以直接全局变量一样使用 --> <div id="app"> <div class="container"> <div class="row"> <h3> 静态请求【 模拟数据 】 </h3> <button type="button" class="btn btn-primary" @click = "getStatic" > getJson </button> <h3> 动态请求 【 真实接口】 </h3> <button type="button" class="btn btn-primary" @click = "get"> get </button> <button type="button" class="btn btn-primary" @click = "post"> post </button> </div> </div> </div> <script src="./lib/vue.js"></script> <script> new Vue({ el:"#app", methods:{ // 请求静态数据 getStatic(){ fetch('./mock/data/data.json') .then(res=>res.json())//做数据格式化的 .then(data=>console.log(data))//获取数据格式化之后的结果 .catch(error=>console.log(error))//错误捕获 }, get(){ fetch('http://localhost/get.php?a=1&b=2') .then(res=>res.text()) .then(data=>console.log(data)) .catch(error=>console.log(error)) }, post(){ fetch('http://localhost/get.php?a=1&b=2',{ method:'POST',//或PUT body:new URLSearchParams([["a",1],["b",2]]).toString(), headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }) }) .then(res=>res.text()) .then(data=>console.log(data)) .catch(error=>console.log(error)) } } }) </script>
-
-
封装
-
jq
-
vue 1.x vue-resource 弃用
-
axios现如今最好的封装的请求库
- axios:
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script> <!-- 引入axios cdn之后会得到一个axios的全局变量 --> </head> <body> <div id="app"> <div class="container"> <div class="row"> <h3> 静态请求【 模拟数据 】 </h3> <button type="button" class="btn btn-primary" @click = "getStatic" > getJson </button> <h3> 动态请求 【 真实接口】 </h3> <button type="button" class="btn btn-primary" @click = "get"> get </button> <button type="button" class="btn btn-primary" @click = "post"> post </button> </div> </div> </div> <script src="./lib/vue.js"></script> <script> // 以下代码是统一设置post请求的请求头 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; new Vue({ el:"#app", methods:{ // 获取静态数据 getStatic(){ // console.log(axios({}))//Promise {<pending>} 证明axios它底层封装的Promise axios({ url:'./mock/data/data.json', method:'GET' }).then(res=>console.log(res)) .catch(error=>console.log(error)) }, // 动态请求数据 get(){ // 写法一 // axios({ // url:'http://localhost/get.php',//www下面的get.php文件 // method:'GET', // params:{ // a:1, // b:2 // } // }).then(res=>console.log(res)) // .catch(error=>console.log(error)) // 写法二 //axios // .get('http://localhost/get.php',{ // params:{ // a:1, // b:2 // } // }).then(res=>console.log(res)) // .catch(error=>console.log(error)) }, post(){ const params=new URLSearchParams() params.append('a',1) params.append('b',2) axios({ method:'post', url:'http://localhost/post.php', data:params }).then(res=>console.log(res)) .catch(error=>console.log(error)) } } }) </script>
- axios和vue-resource相似度 98%
-
深入响应式原理 【 数据驱动原理/ 双向数据绑定原理 】 【 面试题 - 王者 】
-
深入响应式原理
- 数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新
<div class="box"> </div> <button> 点击 </button> <script> /* 深入响应式原理:数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新 使用原生js来实现深入响应式原理 */ let box=document.querySelector('.box') let but=document.querySelector('button') var data={ name:'' } but.onclick=function(){ data.name="zhansghan" //点击修改数据 } // Object.defineProperty(obj,对象的某一个属性) // Object.defineProperty( data, 'name',options) Object.defineProperty(data,'name',{ get(){//给对象提供getter return "历史"//给对象赋初始值 赋值一次 }, set(val){//给对象提供setter //val值得就是对象属性的新值 console.log(val) box.innerHTML=val } }) box.innerHTML=data.name </script>
-
数据驱动
- 数据改变,视图改变
-
双向数据绑定原理
- 使用v-model这个指令来实现,数据改变,视图改变,视图改变,数据也随之改变
-
共用:
vue是通过数据劫持和订阅发布来进行深入响应的,数据劫持指的是,vue通过es5的Object.defineProperty属性对data选项中的数据进行getter和setter设置,订阅发布指的是vue通过之定义自定义事件将data的变化反映到视图上去,vue通过observer观察者对象反应数据的变化,然后通知vue生成新的Virtual DOM ,进而渲染视图 -
关键词:
数据劫持
订阅发布
es5 Object.defineProperty getter setter
observer对象
将data选项中的数据全部做一遍getter和setter设置,然后他们的变化就会被observer监听到
Vue3.0会将 es5的Object.defineProperty 改用 es6/7 的observer