初始化文件夹,并安装vue
cnpm init -y
cnpm add vue
在根目录下新建html文档(index.html)
VS code 生成html模板的快捷键:! + tab
引入vue.js
<script src="./node_modules/vue/dist/vue.js"></script>
创建vue实例,实现数据绑定
<div id="app">{{msg}}</div>
let vm = new Vue({
data:{ //把data里的数据绑定到视图上,其实就是模板引擎 ejs的原理(with),把data作为上下文
msg:"hello"
},
el:"#app" //将实例挂载到普通的dom元素 不能是body、html
})
vm.msg = "aaa"
vue2.0 实现数据响应式变化 用的是Object.defineProperty (不支持数组)
模拟数据响应式渲染
let obj = {
name:"张三",
location:{
x:100,y:100
}
}
function render(){
console.log('渲染视图')
}
//监听
function observer(obj){
if(typeof obj == 'object'){
for(let key in obj){
defineReactive(obj,key,obj[key])
}
}
}
function defineReactive(data,key,value){
observer(value)
Object.defineProperty(data,key,{
get(){
return value
},
set(newValue){
render()
value = newValue
}
})
}
observer(obj)
obj.location.x=200
以上代码可以监听对象原有属性的修改,如果想要新增一个属性则监听不到,有2种解决办法:
$set(obj,'a',1) //可以随意对象新增属性 包含根级obj
obj.location = {...obj.location,a:1} //因为监听的是obj里面的属性,所以不能监听obj本身
$set 原理
function $set(data,key,value){
defineReactive(data,key,value)
}
如果是数组,需要重写数组的方法
let methods = ['push','pop','shift','unshift','splice','sort','reverse'];//只对这7种会改变原数组的方法重写
//拿到数组原型上的方法
let arrProto = Array.ProtoType;
//Object.create()创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
let proto = Object.create(arrProto)
methods.forEach( method=>{
proto[method] = function(){ //AOP
render();
arrProto[method].call(this,...arguments)
}
})
function render(){
//渲染元素
}
function observer(obj){
if(Array.isArray(obj)){
obj.__proto__ = proto
return
}
if(typeof obj == 'object'){
//如果是对象。。。如上
}
}
let arr=[1,2,3,4,5]
observer(arr)
//$set $Set(arr,0,10)
function $set(data,key,value){
if(Array.isArray(data)){
//把数组第0位改为1 内部使用splice 因为可改变原数组,重写了这个方法
return data.splice(key,1,value)
}
}
//不能修改数组长度,例如 arr.length--
//不支持数组内容发生变化 必须通过以上7种方法出发更新 或者替换成新的数组