(1).响应式数据
1.响应式数据和普通数据
<body>
<!-- dom -->
<button onclick="fn()">dom </button>
<div id="box">
</div>
<!--vue -->
<button onclick="fnapp()">vue</button>
<div id="app">
{{msg}}
</div>
<script>
var data ={msg:["heeee",99]}
var box = document.querySelector("#box")
box.innerHTML=data.msg //改变的是box节点的值
function fn(){
data.msg=555; // data.msg的值改变并不会让box节点值改变,除非再次执行box.innerHTML
}
var app = document.querySelector("#app")
var vm = new Vue({
el: '#app',
data: {
msg:"hello"
}
})
function fnapp(){
vm.msg="66" //会改变页面的值,响应式布局。相当于再次执行了app.innerHTML
}
</script>
</body>
2.响应式数据原理代码
<body>
<div id="myapp">
<!-- <div v-html="html">{{msg}}</div> -->
<h1 id="title"></h1>
<p id="msg"></p>
</div>
<script>
function MyVue(option) {
let _myvm = {}
let arr = Object.keys(option.data)
let arr1 = {} //设置的值保存的地方
for (let i = 0; i < arr.length; i++) {
Object.defineProperty(_myvm, arr[i], {
set(v) {
// 劫持
option.data[arr[i]] = v
// arr1[arr[i]] = v
// 响应数据实现
let title = document.querySelector("#title")
title.innerHTML = _myvm["title"]
let msg = document.querySelector("#msg")
msg.innerHTML = _myvm["msg"]
},
get() { //_myvm,对arr[i]的属性值 取操作时候执行
return option.data[arr[i]]
// return arr1[arr[i]]
},
})
_myvm[arr[i]] = option.data[arr[i]]
}
// Object.defineProperty(obj, "a", {
// set() { }, //obj的a属性设置值时调用
// get() { }, //obj的a属性取值时调用
// })
// 劫持了option里面的data的对象值,未来使用_myvm(this),因为设置了set方法,就响应数据,把网页数据更新
return _myvm
}
var myvm = new MyVue({
el: "#myapp",
data: {
title: "mytitle1",
msg: "mymsg"
}
})
myvm.title=1
myvm.msg=1
console.log(myvm.data);
</script>
</body>
3.面试题
1.什么是响应式数据
如果内存中的数据变化了 页面UI也会动态跟着刷新 这种数据就是响应式数据
2.响应式数据设计原理:
1)vue2.0 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
2)ue3.0 --使用es6 proxy 代理了data对象
vue2.0对于一些特殊的引用数据,比如数组取下标的方法就劫持不了,若通过改变data中的arr[0]=1,就劫持不了,就没有响应数据,所以vue3.0就代理整个data对象。
this.arr[2]="hello"//没有劫持数组的下标(不能刷新页面)
解决:
1)
Vue.set(this.arr,2,"hello")//vue帮我们刷新页面,将数组arr的下标2,改为"hello"
this.$set(this.arr,2,"hello")//vue帮我们刷新页面
2)
使用数组自带的方法,如splice()\push()
this.arr.splice(2,1,"hello")//劫持了数组的方法(可以刷新页面)
(2).双向数据绑定
<body>
<div id="app">
<p>1.如果数据容器中的数据变了也会让页面刷新(dom操作让页面改变)</p>
<p>2.如果用户操作dom,改变了页面,反之也会让数据容器中的数据的值改变</p>
<button @click="change1">改变数据容器中的数据</button>
<button @click="look">查看text和数据容器</button>
<p>{{msg}}</p>
<input type="text" :value="msg">
<!-- react实现双向绑定,输入框值改变就触发myinput事件 -->
react:<input type="text" :value="msg" @input="myinput">
<!-- vue实现双向绑定 ,v-model负责监听用户的输入事件来更新数据-->
<input type="text" v-model="msg">
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"hello"
},
methods: {
change1(){
this.msg = "999"
},
look(){
console.log(this.msg); //用户输入框11,this.msg不会改变成11
},
myinput(e){
// console.log();
this.msg = e.target.value
}
},
})
</script>