了解vue双向数据绑定及核心代码模块,以及双向绑定的原理。
通过object.defineProperty()来实现对数据劫持,达到监听目的。
实现mvvm的双向绑定必须实现
1:对所有数据进行监听(.a .b .c这样就算监听 可以修改)
2:解析指令器 例如v-text {{}},还有v-html之类的,解析这些指令的时候都会触发一个方法来进行解析,同时也会调用updater方法来更新(根据指令模板替换数据,以及更新数据)
3:数据发生变化,会通知一个dep对象,dep会通知watcher(二者相关联-有点难)然后进行updater更新界面
vue不支持ie8及以下浏览器 归根到底是ie8不支持 Object.defineProperty这个方法
vue核心是Object.defineProperty
<body>
<div id="test">测试文本</div>
<ul id="fragment_test">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
<script>
一:伪书组转真数组
const lis=document.getElementsByTagName("li");
console.log(lis instanceof Array,lis[1].innerHTML,lis.forEach);//false test2 undefine 伪数组,能用方括号的方法去拿,身上没有foreach属性
//es6通过from api把伪数组转真数组
Array.from(lis)
//Es5实现 截取伪书组里面的全部数组,然后放到一个新的数组
const lis2 =Array.prototype.slice.call(lis)//调用的是空数组的方法 原先方法是指定的空数组,但是加了.call就会把slice变成指定对象lis的方法,会变成一个新数组用lis2接受一下
console.log(lis2 instanceof Array,lis2[1].innerHTML,lis2.forEach);//true 'test2' ƒ forEach(){[native code]}
二: node.nodeType:获取节点类型,只读属性
1:document 最大的节点 element元素节点 attr属性节点 text文本节点
const elementNode=document.getElementById("test")
const attrNode = elementNode.getAttributeNode("id")
const textNode=elementNode.firstChild
console.log(elementNode.nodeType,attrNode.nodeType,textNode.nodeType);//1,2,3
三: 添加修改属性
const obj={
firstName:'A',
lastName:'B'
}
//需求:添加一个fullname的属性 实现自动同步与first和last
Object.defineProperty(obj,'fullName',{
//大括号里面写的是属性描述符
//2:数据描述符
//1:访问描述符
get(){
return this.firstName+"-"+this.lastName
},
set(value){
//赋值的时候可以把字符串转换为数组 前面的复制给firstname 后面的赋值给lastname
const names=value.split("_")//以横线进行分割
this.firstName=names[0]
this.lastName=names[1]
}
})
console.log(obj.fullName);//A-B obj属性获取fullname 自动调用get方法 拿到ab值
obj.fullName='E-F' //自动调用set函数 监视当前属性变化
console.log(obj.firstName,obj.lastName);
//访问描述符
Object.defineProperty(obj,"fullName2",{
configurable:false,//是否可以重新定义
enumerable:true,//是否可以用for in等属性遍历它 没设置默认为false
value:'H-J', //指定初始值
writable:false //value是否可以修改
})
console.log(obj.fullName2);
obj.fullName2='x-y';
console.log(obj.fullName2);//还是HJ
四: object.keys()得到对象自身可枚举的属性值
const names =Object.keys(obj)
console.log(names);
五 :obj.hasOwnproperty(prop): 判断 prop 是否是 obj本身属性 不包括原型身上
console.log(obj.hasOwnProperty('fullName'),obj.hasOwnProperty('toString'));//true false
六 DocumentFragment:文档碎片(高效批量获取更新多个节点)
//Document对应的就是我们显示的页面一但里面的某个元素更新了,界面就会更新
/* <ul id="fragment_test"></ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
举例 ul里面有三个li 当我更改第一个li时 页面就会更新 第二个时候会再次更新 */
//需求,让我修改完全部li之后再更新页面
// 思路 在内存中创建一个fragment 把所有li方法到foragment里面
//(循环遍历进行储存)的同时要把每个li内容进行替换,然后再更新fragment里面的li 这样就会实现
const ul=document.getElementById("fragment_test")
//1:创建fragment
const fragment=document.createDocumentFragment();
//2:取出所有ul中的子节点(回车换行也要取进来)保存到fragment中
let child;//定义一个变量 然后while循环
while(child = ul.firstChild){
fragment.appendChild(child)//向fragment中添加child子元素
//注意appendChild是把ul里面的li拿出来放到fragment里面
//拿出ul的第一个字节点赋值给child ,这样就能进行正常循环了
}
//3:更新所有fragment里面所有li文字
Array.prototype.slice.call(fragment.childNodes).forEach(node=>{
if(node.nodeType === 1){
//不能把空格替换掉 进行判断 如果是元素节点就进行替换
node.textContent = "测试文本1"
}
})
//4:将fragment重新插入到ul里面
ul.appendChild(fragment)
</script>
</body>