vue2与vue3双向数据绑定的区别说明

目录
  • vue2与vue3双向数据绑定区别
    • Vue2双向数据绑定存在的问题
    • 原理
    • vue3.0双向数据绑定Proxy
  • vue语法:数据的双向绑定
    • 1.指令v-model
    • 2.v-model与修饰符
    • 3.v-model与自定义组件

vue2与vue3双向数据绑定区别

新的响应式机制采用了ES6的ProxyApi,抛弃了Object.defineProperty()

Vue2双向数据绑定存在的问题

关于对象: Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对property执行 getter/setter转化,所以property必须在 data对象上存在才能让 Vue 将它转换为响应式的。

关于数组: Vue 不能检测以下数组的变动:

当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue

当你修改数组的长度时,例如:vm.items.length = newLength

在官网深入响应式原理一章有较详细阐述,针对以上两种情况解决方法,官网也有给出答案,那就是使用set方法。

原理

Vue2.0使用Object.defineProperty对象以及对象属性的劫持+发布订阅模式,只要数据发生变化直接通知变化 并驱动视图更新。

 <input type="text" id="in"/> 输入的值为:<span id="out"></span>
var int = document.getElementById('in');
var out = document.getElementById('out');
// 定义一个对象
const data={name:'peak',age:10}
// 遍历对象 实现对对象的属性进行劫持
Object.keys(data).forEach((key) => {
   Object.defineProperty(data, key, {
     // 当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中
     enumerable: true,
     // 当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除
     configurable: true, 
     get: ()=>{ // 一个给属性提供 getter 的方法
       console.info(`get ${key}-${val}`)
       return val;
     },
     set: (newVal)=>{ // 一个给属性提供 setter 的方法
       // 当属性值发生变化时我们可以进行额外操作 如调用监听器
       if(newVal === val ){ // 如果未发生变化 不做其他操作
        return;
       } 
       console.log(`触发视图更新函数${newVal}`);
       out.innerHTML = newVal;
     },
   });   
});
int.addEventListener('input', function(e) {
    obj.name = e.target.value;
})
data.age=25 // 触发set方法 

vue3.0双向数据绑定Proxy

Vue3.0中的响应式采用了ES6中的Proxy方法。

Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)

语法:

const p = new Proxy(target, handler)

参数target表示要使用Proxy包装的对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)

参数handler是一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理p 的行为

let obj = {
    a: 1,
    b: 2
}
const proxy = new Proxy(obj, {
    get: function(target, prop, receiver) {
        return prop in target ? target[prop] : 0
    },
    set: function(target, prop, value, receiver) {
        target[prop] = 666
    }
})
console.log(proxy.a) // 1
console.log(proxy.c) // 0
proxy.a = 10
console.log(proxy.a) // 666
obj.b = 10
console.log(proxy.b) // 不是666 而是10 

以上代码中obj是我们要代理的目标对象,get,set方法是参数handler的两个属性,具体如下:

  • handler.get()接收三个参数,第一个参数target为代理的目标对象,第二个参数prop是代理的目标对象的属性,第三个参数是Proxy或者继承Proxy的对象,通常是proxy本身。
  • handler.set()接收四个参数,其中三个参数都与get方法相同,唯独多出来一个value表示新的属性值。

上述代码表示当访问proxy的属性时,进行拦截判断,该属性是否是目标对象的属性,如果是那么就将其值返回出来,否则就返回0。

当对proxy上的属性进行重写时,将重写的该属性赋值为666。

注意: 此时对数据的劫持,只是劫持了代理对象proxy,而跟原对象obj没有任何关系,对obj进行操作,也不会监听到。

用proxy实现一个简易版的数据响应:

<body>
    <h2 id="app"></h2>
  <input id="input" type="text" />
</body>
let app = document.getElementById('app')
let input = document.getElementById('input')
let obj = { // 源数据
  text:'hello world'
}
let proxy = new Proxy(obj, {
  set: function(target, prop, value){ // input事件触发进行劫持,触发update方法
    target[prop] = value
    update(value)
  }
})
function update(value){ // update方法用于同步dom更新
    app.innerHTML = value
    input.value = value
}
input.addEventListener('input',function(e){ // 监听input数据变化,并修改proxy的值
  proxy.text = e.target.value
})
proxy.text = obj.text // 初始化源数据

vue语法:数据的双向绑定

1.指令v-model

使用v-model可以为输入元素创建数据双向绑定,他会根据元素的类型自动选取正确的方法来更新元素。下面的代码演示了单行文本框、多行文本框、单选按钮,复选框以及下拉选择框做了一个简单的演示。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>指令v-model</title>
</head>
<body>
<div id="app">
    <h3>1.单行文本框</h3>
    <input type="text" v-model="singleText" style="width: 240px;">
    <p>{{singleText}}</p>
    <h3>2.多行文本框</h3>
    <textarea v-model="multiText" style="width: 240px;"></textarea>
    <p>{{multiText}}</p>
    <h3>3.单选框</h3>
    <!--由于点击被选中的单选项无法取消其被选中的状态,所以一般没有使用单个选项的场景,设置v-model共用一个变量(radioValue)可以实现RadioGroup的效果-->
    <input id="ra" type="radio" value="张三" v-model="radioValue">
    <label for="ra">A.张三</label>
    <input id="rb" type="radio" value="李四" v-model="radioValue">
    <label for="rb">B.李四</label>
    <p>{{radioValue}}</p>
    <h3>4.单个复选框</h3>
    <!--单个复选框被用于true和false的切换-->
    <input id="c" type="checkbox" v-model="toggleValue">
    <label for="c">哒哒哒</label>
    <p>{{toggleValue}}</p>
    <h3>5.多个复选框</h3>
    <!--多个复选框,v-model接受数组类型的变量-->
    <input id="ca" type="checkbox" value="AAA" v-model="checkedValues">
    <label for="ca">AAAA</label>
    <input id="cb" type="checkbox" value="BBB" v-model="checkedValues">
    <label for="cb">BBBB</label>
    <input id="cc" type="checkbox" value="CCC" v-model="checkedValues">
    <label for="cc">CCCC</label>
    <p>{{checkedValues.join(',')}}</p>
    <h3>6.单项下拉选择框</h3>
    <select v-model="singleSelect">
        <!--如果没有设置value值,则option节点的文本值会被当做value值-->
        <option value="zhangsan">张三</option>
        <option >李四</option>
    </select>
    <p>{{singleSelect}}</p>
    <h3>7.多项下拉选择框</h3>
    <select multiple v-modle="multiSelect">
        <!--按住Ctrl,可执行多选-->
        <option value=1>语文</option>
        <option value=2>数学</option>
        <option value=3>历史</option>
        <option :value="4">地理</option>
    </select>
    <p>{{multiSelect.join(',')}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script>
    var app = new Vue({
        el:'#app',
        data(){
            return{
                singleText:'',
                multiText:'',
                radioValue:'',
                toggleValue:false,
                checkedValues:[],
                singleSelect:'zhangsan',
                multiSelect:[1,3]
            }
        },
        methods:{
        }
    });
</script>
</body>
</html>

2.v-model与修饰符

修饰符 可用版本 说明
.lazy 所有 将用户输入的数据赋值于变量的时间有输入时延迟到数据改变时
.number 所有 自动转换用户输入为数值类型
.trim 所有 自动过滤用户输入的首尾的空白字符

下面的代码展示了trim和number的简单用法。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-model与修饰符</title>
</head>
<body>
<div id="app">
    <input type="text" v-model.trim.number="text" @keyup="handleKeyUp">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script>
    var app = new Vue({
        el:'#app',
        data:()=>({
           text:''
        }),
        methods:{
            handleKeyUp(event) {
                console.log(this.text,typeof this.text)
            }
        }
    });
</script>
</body>
</html>

3.v-model与自定义组件

在自定义组件中,value属性和input事件尤为重要,value属性用于接收外部传入的值以更新组件内部的状态,input事件由开发者决定在什么事件调用。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-model与修饰符</title>
</head>
<body>
<div id="app">
    <!--自定义组件-->
    <custom-screen v-model="text"></custom-screen><br>
    <input type="text" v-model.trim.number="text">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script>
    Vue.component('custom-screen',{
        //使用value属性接收外部传入的值
        props:['value'],
        methods: {
            handleReset(){
                console.log('重置为\'\'');
                this.$emit('input','');//使用$emit发送input事件,并将目标值作为参数传出
            }
        },
        template:'<div>\n' +
            '    <h2>输入值为:{{value}}</h2>\n' +
            '    <button @click="handleReset">重置为空</button>\n' +
            '</div>'
    })
    var app = new Vue({
        el:'#app',
        data:()=>({
           text:''
        }),
        methods:{
        }
    });
</script>
</body>
</html>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Vue2.0/3.0双向数据绑定的实现原理详解

    Vue2.0/3.0 双向数据绑定的实现原理 双向数据绑定简意 即数据的改变能让页面重新渲染 Vue2.0 ES5的原理: Object.defineProperty 对数据进行拦截 简单小案例 <body> 姓名: <span id="name"></span> <br /> <input type="text" id="inputName" /> </body> 改变in

  • vue3.0中的双向数据绑定方法及优缺点

    熟悉vue的人都知道在vue2.x之前都是使用object.defineProperty来实现双向数据绑定的 而在vue3.0中这个方法被取代了 1. 为什么要替换Object.defineProperty 替换不是因为不好,是因为有更好的方法使用效率更高 Object.defineProperty的缺点: 1. 在Vue中,Object.defineProperty无法监控到数组下标的变化, 导致直接通过数组的下标给数组设置值,不能实时响应. push() pop() shift() unsh

  • Vue2.x和Vue3.x的双向绑定原理详解

    双向的绑定的原理 通过Object.defineproperty()重新定义对象属性的set方法.get方法来实现的,从这个属性中取值时会触发get方法,改变这个属性时会触发set方法,所以我们只要将一些需要更新view的方法放在这里面就可以实现data更新view了,而view更新data其实可以通过事件监听实现 当视图上的数据发生改变时, data 中的数据也发生改变当 data 中的数据发生改变时,视图中的数据也发生改变 Object.defineProperty() Object.def

  • 稍微学一下Vue的数据响应式(Vue2及Vue3区别)

    什么是数据响应式 从一开始使用 Vue 时,对于之前的 jq 开发而言,一个很大的区别就是基本不用手动操作 dom,data 中声明的数据状态改变后会自动重新渲染相关的 dom. 换句话说就是 Vue 自己知道哪个数据状态发生了变化及哪里有用到这个数据需要随之修改. 因此实现数据响应式有两个重点问题: 如何知道数据发生了变化? 如何知道数据变化后哪里需要修改? 对于第一个问题,如何知道数据发生了变化,Vue3 之前使用了 ES5 的一个 API Object.defineProperty Vue

  • vue2与vue3双向数据绑定的区别说明

    目录 vue2与vue3双向数据绑定区别 Vue2双向数据绑定存在的问题 原理 vue3.0双向数据绑定Proxy vue语法:数据的双向绑定 1.指令v-model 2.v-model与修饰符 3.v-model与自定义组件 vue2与vue3双向数据绑定区别 新的响应式机制采用了ES6的ProxyApi,抛弃了Object.defineProperty() Vue2双向数据绑定存在的问题 关于对象: Vue 无法检测 property 的添加或移除.由于 Vue 会在初始化实例时对prope

  • Vue2 与 Vue3 的数据绑定原理及实现

    目录 介绍 Object.defineProperty Proxy 介绍 数据绑定是一种把用户界面元素(控件)的属性绑定到特定对象上面并使其同步的机制,使开发人员免于编写同步视图模型和视图的逻辑. 观察者模式又称为发布-订阅模式,定义对象间的一种一对多的依赖关系,当它本身的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.比如用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就同步显示在界面上.这样可以确保界面和数据之间划清界限,假定应用程序的需

  • 手动实现vue2.0的双向数据绑定原理详解

    一句话概括:数据劫持(Object.defineProperty)+发布订阅模式 双向数据绑定有三大核心模块(dep .observer.watcher),它们之间是怎么连接的,下面来一一介绍. 为了大家更好的理解双向数据绑定原理以及它们之间是如何实现关联的,先带领大家复习一下发布订阅模式. 一.首先了解什么是发布订阅模式 直接上代码: 一个简单的发布订阅模式,帮助大家更好的理解双向数据绑定原理 //发布订阅模式 function Dep() { this.subs = []//收集依赖(也就是

  • 由浅入深讲解vue2和vue3的区别

    目录 前言 vue2 vs vue3 对比 双向绑定更新 实例化 生命周期 获取props 数据和方法的定义 给父组件传值emit watchEffect 组件通信 注意 路由 总结 前言 vue2和vu3之前的区别,一直以来是面试必考题目,如何回答,回答的层次决定了面试者的对于vue2,3的理解,以及对于vue3目前稳定版本发展的方向的了解,即考察使用程度,又考察了学习能力,可以说是回答即可以很简单,也可以很不简单,这里需要注意的是面试官的面试程度,需要我们层层递进,由浅入深来回答,这样可以体

  • Vue2与Vue3兄弟组件通讯bus的区别及用法

    目录 vue2.x vue3.x tiny-emitter插件用法 mitt插件用法 vue2.x Vue.prototype.$bus=new Vue() 监听: this.$bus.$on('方法名',(参数)=>{}),它可以累加 触发: this.$bus.$emit('方法名',实参值) 销毁:this.$bus.$off('方法名'),谁监听谁销毁 注意: 由于监听可以累加, 所以必须要有第四步销毁 vue3.x tiny-emitter插件用法 安装插件 npm i tiny-em

  • vue2与vue3中生命周期执行顺序的区别说明

    目录 vue2与vue3中生命周期执行顺序区别 生命周期比较 简单例子说明 三种情况下的生命周期执行顺序 1.单页面下生命周期顺序 2.父子.兄弟组件的生命周期顺序 3.不同页面跳转时各页面生命周期的执行顺序 vue2与vue3中生命周期执行顺序区别 生命周期比较 vue2中执行顺序 beforeCreate=>created=>beforeMount =>mounted=>beforeUpdate =>updated=>beforeDestroy=>destro

  • Vue响应式原理及双向数据绑定示例分析

    目录 前言 响应式原理 双向数据绑定 前言 之前公司招人,面试了一些的前端同学,因为公司使用的前端技术是Vue,所以免不了问到其响应式原理和Vue的双向数据绑定.但是这边面试到的80%的同学会把两者搞混,通常我要是先问响应式原理再问双向数据绑定原理,来面试的同学大都会认为是一回事,那么这里我们就说一下二者的区别. 响应式原理 是Vue的核心特性之一,数据驱动视图,我们修改数据视图随之响应更新,就很优雅~ Vue2.x是借助Object.defineProperty()实现的,而Vue3.x是借助

随机推荐