1. v-model原理 :是基于@input/change和v-bind:value封装的语法糖

     @input/change底层是 JS事件监控 V同步M
      v-bind:value底层是    JS的 Object.defineProperty监控 M同步V    

<div id="root">

  <h1>v-model</h1>
  <input type="text" v-model="msg" />

  <h1>【v-bind:value】和【@input】 好理解版本</h1>
  <input type="text" v-bind:value="msg2" @input="changeMsgFn" />

  <h1>【v-bind:value】和【@input】 简写</h1>
  <input type="text" v-bind:value="msg3" @input="msg3 = $event.target.value" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      msg: '你好',
      msg2: '你好2',
      msg3: '你好3'
    },
    methods: {
      changeMsgFn(evt) {
        // console.log(evt.target.value)
        this.msg2 = evt.target.value
      }
    }
  })
</script>

2.VUE双向绑定/响应式原理

通过触发事件打印vue模型数据,发现每个模型数据都有getter、setter方法,代表使用了 Object.defineProperty进行数据劫持

①语法: 仅监控你写的属性,数组对象监控不到里面键的变化

语法单词configurableenumerablevaluewritablegetset
作用能否删除能否枚举/遍历重置默认值能否修改值劫持获取劫持更新
数据描述符可以可以可以可以不可以不可以
存取描述符可以可以不可以不可以可以可以

 数据描述符:

<script>
// 1 定义模型
let data = {
    uname: '张三',
    sex:'男'
}

// 2 数据劫持         监控data中的uname属性并进行操作
Object.defineProperty(data, 'uname', {
    configurable: false, // 能否删除:true是,false否
    enumerable: false,    // 能否枚举/遍历:true是,false否
    value: '你好',       // 重置uname默认值 
    writable: true,     // 能够修改值:true是,false否
})

// 3 练习 数据描述符(也就是劫持 控制数据后期的操作
console.log('能否删除,删前', data)
delete data.uname
console.log('能否删除 删后', data)


for (let key in data){
    console.log('枚举结果:', key, data[key])      // data.uname、data.sex
}
console.log('最新数据:', data)
data.uname = '李四'
console.log('更新后的数据:', data)
</script>

存取数据描述符:

<script>
// 1 定义模型
let data = {
    uname: '李焕英',
    sex: '女',
}

// 2 数据劫持   
let tmp = data.uname  // 留心传值  互不影响  否则无限死循环
Object.defineProperty(data, 'uname', {
    configurable: true,	
    enumerable: true,
    get() {  // 获取uname数据时运行get方法 V-M              
        // 发现:console.log(data.uname) 居然返回undefined
        // 原因:因为uname属性被监控了,遇到打印获取动作先走get过滤,然后再返回
        // 留心:get返回什么就是什么,因为它是数据劫持者
        // 所以:你没写return 就是undefined打印出来
        // 思考:return什么呢
        // 回答:data.uname
        // return data.uname
        // 发现:上述语法死循环
        // 原因:第一次get外面使用,触发get方法,然后get方法自己用,触发get方法; 自己用 触发get方法....
        // 解决:在外面定义临时变量存放数据  get里面返回
        return tmp
    },
    
    set(newval) { // 更改数据时运行set方法 同步到视图  M-V
        console.log(`键被set修改成:`, newval)        
        // 发现:更新数据,可以触发set方法
        // 但是:更新完了之后,外面打印还是旧数据
        // 原因:为了避免死循环,不能直接操作监控的数据,所以我们返回的tmp
        // 因此:更新后也得同步tmp
        tmp = newval
        // 发现:好了
        // 铺垫:后期我们就在set方法中劫持数据更新同步到视图
        // document.querySelector(选择器).value = newval
    }
})

console.log(data.uname)  //李焕英
data.uname = '来试试更新'
console.log(data.uname)   //来试试更新
</script>
Logo

前往低代码交流专区

更多推荐