MVVM
v层可以拿到全部的vm层
数据代理
**Object.defineProperty()**方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty(obj, prop, descriptor)
obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符。
由Object.defineProperty()所定义的属性是不可枚举的,无法被遍历出来。 除非在第三个参数对象的属性中将属性enumerateble设置为true ,还有一些其他的属性。
getter和setter
Vue中对data读取用的就是getter和setter,data一旦变化页面也会重新渲染。
而Vue中的数据更改就是 Vue实例代理_data更改其中的数据
由于data一改变页面上用到的数据就要重新改变。所以在_data中不单单是对data进行一个值得获取,还做了数据劫持。
通过obj2代理操作obj1的x属性
Vue检测数据改变的原理
先简单的实现下Vue核心的代码片段(因为Vue考虑的情况更多更复杂)
let data= {
name: zhangSan;
age: 66;
}
// 创建一个监视的实例对象,用于监视data中的属性变化
const obs = new Observe(data)
console.log(obs)
function Observe (obj){
// 汇总对象中所有属性作为一个数组
const keys = Object.keys(obj)
//遍历
keys.forEach((k)=> {
// -----精华---- this 指向更改,从之前指向data会产生无限回调导致堆栈溢出
// 而更改后this指向Observe的实例对象obs
Object.defineProperty(this,k,{
get(){
return obj[key]
}
set(k){
console.log(`${k}被改了`)
obj[k] = val
}
})
})
}
事件处理
在Vue 的math中挂载的事件中的this指向的是Vue实例,如果是箭头函数则指向父级Window
$event占位event。
事件修饰符
修饰符名称 | 作用 |
---|---|
.stop | 阻止单击事件继续传播 |
.prevent | 提交事件不再重载页面 |
.capture | 添加事件监听器时使用事件捕获模式,即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 |
.self | 只当在 event.target 是当前元素自身时触发处理函数 |
.once | 点击事件将只会触发一次,即事件不是从内部元素触发的 |
.passive | 滚动事件的默认行为 (即滚动行为) 将会立即触发,而不会等待 onScroll 完成 , 修饰符尤其能够提升移动端的性能,passive会告诉浏览器你不想阻止事件的默认行为 |
按键修饰符 | <组件 @keyup.13=“fn” />.enter .tab .delete (捕获“删除”和“退格”键) .esc .space .up .down .left .right |
原生事件 | 自定义组件中可以自定义一些事件,可以通过 .native修饰符来指定监听原生中的事件,而不是组件自定义事件 |
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击。
而 v-on:click.self.prevent 只会阻止对元素自身的点击。
滚动事件:
/ | 滚轮滚动wheel | 滚动条滚动scroll |
---|---|---|
区别 | 滚轮滚动一次触发一次 | 滚动一下次触发一次 |
执行原理 | 先触发scroll绑定的函数,后移动页面的ui 用wheel.passive 优先执行默认行为 | scroll默认先处理滚动事件 |
computed计算属性
watch
watch的配置项
v-for的key原理
key原理
虚拟DOM中key的作用
key是对象中的唯一标识,当数据发生变化时,Vue会根据新数据生成新的虚拟dom,随后vue进行新虚拟DOM与旧虚拟DOM的差异比较。
对比规则
- 旧虚拟dom中找到与新虚拟dom中相同的key
① 若虚拟DOM中内容没变直接复用之前的真实DOM
②若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面的真实DOM- 旧虚拟DOM中未找到与真实DOM中相同的key
创建新的真实DOM,并渲染到页面
对比算法
对号表示可复用 叉号表示不可复用
乱序插入会导致对比失败
当diff算法对比无差错后,就可以直接复用之前的,不需要将后面未改动的item进行修改重建。
计算属性computed
computed 会在页面加载时调用一次 ,以及所依赖的数据发生改变时调用。
vue.set(obj,key,value)
vue.set不能给Vue实例和实例上的对象添加属性,只能给实例上的对象的对象添加属性
Vue数组更新
vue中规定提供了修改数组的api,直接通过下标赋值是无法触发页面更新。
Vue.arr.push 不等于 Arr.prototype .push
Vue的push对普通的push进行了包裹,使得他可以触发页面更新
目前有且仅有的七个方法
v-model修饰符
Vue 过滤器
限制:
vue内置命令
内置命令 | 实现效果 |
---|---|
v-text | 替换标签内的内容 |
v-html | 替换标签内的内容并解析HTML语义 |
v-cloak | Vue没有介入dome时显示该属性,否则该属性消失,和CSS搭配使用可以解决代码闪屏问题 |
v-once | 只显示初始化时的data |
v-pre | 跳过其所在节点的编译过程 |
自定义指令
//v-??在directives中定义
directives{
//big函数何时会被调用:简写方式只相当于下面的bind和update中
//1. 指令与元素成功绑定时(一上来)2.指令所在模板被重新解析时
big(element | binding){
}
//写成完整的对象形式有三个常用的API
fbind:{
//指令与元素成功绑定时
bind(element, binding){}
//指令所在元素被插入页面时
inserted(element, binding){}
//指令所在模板被重新解析时
update(element, binding){}
}
}
定义时会踩的坑:
- 命名时不能用小驼峰,它会自动转译成全小写
- ‘-’ 连字符要用引号引起来并写成key:function(){}的形式推荐
- 指令中的this都是指向window
内置的原型关系
实例的原型对象永远指向他缔造者的原型对象
vueCompontent.prototype._proto_===Vue.prototype
制作这层关系是为了让组建实例对象vc,可以访问到Vue原型上的属性和方法