虚拟dom 是根据模板生成一个js对象(使用createElement方法),根据这个js对象再去生成真实的dom,对复杂的文档DOM结构,提供一种方便的工具,
进行最小化的DOM操作diff算法。 当data发生改变 会根据新的数据生成一个新的虚拟dom ,新的虚拟dom和旧的虚拟dom进行对比,这个对比的过程就是diff算法,
但是因为这种机制也给代码运行带来了一些压力 效率低 消耗内存。一些不变的数据,例如常量,不会去修改它是不需要对比的,vue3是将变量赋值flag1,不变的值赋值flag,只会对比变动的值,因此比vue2性能更好他会查找模板中不同的数据,如果发现数据有不同就重新渲染模板。
附上理解图
Vue3 diff 势必会成为流行趋势
在Vue3中diff是找变量判断不同处,如果是一个写死的值,根本不会变,
所以不需要diff判断,变量绑定flag1,
死值是flag,diff只找flag1的判断是否不同,在渲染操作,所以Vue2速度要快
v-model 通常使用在表单元素中 他是一个数据双向绑定的指令
一、vue和vue3的双向数据绑定
Vue2是采用observer观察者对数据劫持结合发布者-订阅者模式,
通过Object.defineProperty()将data中的所有的数据包括子属性对象的属性
都添加上了getter/setter方法,,通过compile去解析模板和"{{}}" ,
当数据发生变化利用watcher里面的update方法通知compile更新模板 ,
watcher就是用来监听页面数据变化的,wacther结合了observer观察者和complie指令解析器
二、 Vue2使用Object.defineProperty()的缺点
对于数组而言,大部分操作都是拦截不到的,只是 Vue 源码中通过重写函数的方式解决了这个问题。
七个编译数组的方法
比如通过下标方式修改数组数据或者给对象新增属性,这都不能触发组件的重新渲染,因为 Object.defineProperty 不能拦截到这些操作。
三、Vue3是通过Object.define.proxy 对对象进行代理,从而实现数据劫持。
使用Proxy 的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,
因为 Proxy 是 ES6 的语法
当然他可以绑定到组件上:
在大部分情况下, v-model 等价于 :value 和 @input事件的组合,
比如:下拉框 单选框 多行文本textarea绑定的就是@input=valueOfText=$event.target.value
在编程思想上,这种帮助使用者『隐藏细节』的方式叫封装
冷知识: 如果v-model绑定了相应式对象里不存在的值,vue会自动增加这个属性,并且是响应式的,
通俗总结:data中的user对象有name属性,没有age属性,但是v-model="user.age",user中就会增加一个相应式属性age
面试官: 如何让你开发的组件支持 v-model
答:组件使用v-model相当于在组件上添加:value @input事件,可以通过model属性自定义设置,
与data、props同级
在定义 vue 组件时,你可以提供一个 model 属性,用来定义该组件以何种方式支持 v-model。
model 属性本身是有默认值的,如下:
// 默认的 model 属性 export default { model: { prop: 'value', event: 'input' } }
/* 子组件 */ <template> <div> 我几岁:{{ propsAge }} <el-button @click="age(1)">加</el-button> <el-button @click="age(-1)">减</el-button> <!-- 5+(-2)=3 --> </div> </template> <script> export default { props: { propsAge: { // 子组件接受的类型 type: Number, } }, model: { // 自定义v-model的格式 prop: 'propsAge', // 代表 v-model 绑定的prop数据名 event: 'ev' // 代码 v-model 通知父组件更新属性的事件名 }, methods: { age(num) { const sum = this.propsAge + num // 传到父组件,让父组件可以操作 this.$emit('ev', sum) } } } </script>
/* 父组件 */ <template> <div id="about"> <Hello-world v-model="d"></Hello-world> </div> </template> <script> import HelloWorld from '../components/HelloWorld.vue' export default { data() { return { d: 8 }; }, components: {HelloWorld}, }; </script>