声明
以下均来自b站尚硅谷总结
想让vue工作,就必须创建一个vue实例,且要传入一个配置对象
root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法
root容器里的代码被称为【vue模板】
一个重要的原则:由vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是vue实例了【箭头函数没有自己的this,要往外找】
Object.defineProperty方法
let Person = {}
let temp = null
Object.defineProperty(Person, 'name', {
get: function () {
return temp
},
set: function (val) {
temp = val
}
})
使用该方法定义的obj属性不能进行枚举
如:person: {
name: 'Bob',
age: 18,
}
Object.keys(person) // 输出['name','age']
person: {
name: 'Bob',
}
Object.defineProperty(person, 'age',{
value: 18
})
Object.keys(person) // 输出["name"]
// 若想用它枚举出来可写属性enumerable: true // 控制属性是否可枚举,默认值false
person:{
name: 'Bob',
}
Object.defineProperty(person, 'age',{
value: 18,
enumerable: true
})
Object.keys(person) // 输出['name','age']
vue中的数据代理【https://www.bilibili.com/video/BV1Zy4y1K7SH?p=13&spm_id_from=pageDriver】
vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写) vue中数据代理的好处:更加方便的操作data中的数据
基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上,为每一个添加到vm中的属性都指定一个getter和setter,在getter/setter中操作(读/写)data中的属性
计算属性使用过一次后进行缓存,在两种情况下get方法被调用:
(1)初次读取;(2) 所依赖的数据发生变化时
监听watch可以开启异步任务,计算属性不行。主要因为watch依靠自己亲自写代码修改,而计算属性依靠的是返回值。
参考【https://www.bilibili.com/video/BV1Zy4y1K7SH?p=25】另外:定时器里的函数并不是vue所管理的函数
①computed能完成的功能watch都可以完成
②watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
两个重要的小原则①所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
②所有不被vue所管理的函数(定时器的回调函数、ajax的回调函数等、promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象
即:所有被vue所管理的函数要写成普通函数,其余写成箭头函数,目的是让this的指向为vm或组件实例对象
【https://www.bilibili.com/video/BV1Zy4y1K7SH?p=34&spm_id_from=pageDriver】
let person = {
name: '小明',
age: 18
}
// vue2的响应式原理
// let p = {}
// let observerFun = function(obj){
// for (const item of Object.keys(obj)) {
// Object.defineProperty(p,item,{
// get() {
// console.log(item+'属性被读取了')
// return person[item]
// },
// set(val) {
// console.log(item+'属性被修改了')
// person[item] = val
// }
// })
// }
// }
// const obs = new observerFun(person)
// vue3的响应式原理
const p = new Proxy(person, {
get(target, propName) {
console.log(`p身上的${propName}属性被读取`)
// return target[propName]
return Reflect.get(target, propName)
},
set(target, propName, value) {
console.log(`p身上的${propName}属性被修改为${value}`)
// target[propName] = value
Reflect.set(target, propName)
},
deleteProperty(target, propName) {
console.log(`p身上的${propName}属性被删除`)
// delete target[propName]
Reflect.deleteProperty(target, propName)
}
})
查看less版本(其他也可以),npm view less-loader versions
setup() {
let msg = myRef('hello')
function myRef(val) {
return customRef((track, trigger) => {
let timer
return {
get() {
console.log('有人读取myRef了')
track() // 通知vue去追踪value的变化
return val
},
set(newVal) {
clearTimeout(timer)
timer = setTimeout(() => {
val = newVal
trigger() // 通知vue重新解析模板
},1000)
}
}
})
}
return {
msg
}
}
vue2中采用构造函数模式,vue3中改为工厂模式
工厂方法是延迟到子类中进行,构造函数没有显式的创建对象;直接将属性和方法赋给了this对象;没有return 语句;要创建Person的新实例,必须使用new操作符。
vue3中对不同数据处理方式不同,ref创建对象自动转换为proxy处理数据
1、比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现:
// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() {
this.$emit("mounted");
}
以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示:
// Parent.vue
<Child @hook:mounted="doSomething" ></Child>
doSomething() {
console.log('父组件监听到 mounted 钩子函数 ...');
},
// Child.vue
mounted(){
console.log('子组件触发 mounted 钩子函数 ...');
},
// 以上输出顺序为:
// 子组件触发 mounted 钩子函数 …
// 父组件监听到 mounted 钩子函数 …
当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。