computed和watch的区别
computed是计算属性。用来计算一个相对复杂的表达式,然后返回,并且内部会缓存该值。如果收集的依赖项未变化,那么他就直接返回上次计算的值,将不重新计算。内部是用过_dirty
来控制是否使用缓存的。
源码位置:packages/reactivity/computed.ts
watch主要是监听依赖的变化,然后做一些逻辑处理。注意watch监听,对于reactive对象来说,他返回的新旧值都是一样的,因为都是同一个引用。但是对于监听普通的值和对象(只对第一层属性来说,改变其他层的属性,依旧是新旧值都一样的。),那么他会返回的新旧值就不一样了。
我个人感觉,开发中监听一个一个普通值的是最常见的。
data为什么是个函数,而不是对象
因为它需要为每一个实例创建唯一的data引用,每次创建组件实例,如果data是函数的话,每次返回的对象都是不同的,防止数据紊乱。
为了防止多个组件对象之间共用一个data
,产生数据污染。
watch能监听computed的属性吗
可以监听,因为computed也是返回一个ref对象
Vue.createApp({ template: ` <div> <p>{{computedVal}}</p> <button @click="handleClick">改变computed</button> </div> `, setup (props) { const refVal=Vue.ref("pp") let computedVal=Vue.computed({ get () { return refVal.value }, set (newVal) { refVal.value=newVal } }) const handleClick=() => { console.log("=====") computedVal.value="oo" } Vue.watch(computedVal,(v1,v2) => { console.log("v1",v1) // oo console.log("v2",v2) // pp }) return { computedVal, handleClick } } }).mount("#app")
vue的响应式原理
重学vue(2, 3)及其生态+TypeScript 之 vue部分实现和源码分析
vue的生命周期
- beforeCreate: 在实例初始化之后、进行数据侦听和事件/侦听器的配置之前同步调用。
- created:在实例创建完成后被立即同步调用。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且
$el
property 目前尚不可用。
- setup 取代 beforeCreate, created
- beforeMount: 在挂载开始之前被调用:相关的
render
函数首次被调用。
- mounted:在实例挂载完成后被调用,这时候传递给
app.mount
的元素已经被新创建的vm.$el
替换了。如果根实例被挂载到了一个文档内的元素上,当mounted
被调用时,vm.$el
也会在文档内。 注意mounted
不会保证所有的子组件也都被挂载完成。如果你希望等待整个视图都渲染完毕,可以在mounted
内部使用vm.$nextTick
- beforeUpdate:在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
- updated:在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。注意,
updated
不会保证所有的子组件也都被重新渲染完毕。如果你希望等待整个视图都渲染完毕,可以在updated
内部使用vm.$nextTick
。
- beforeUnmount:在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
- unmounted:卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
被keep-alieve缓存组件的生命周期:
- activated:被 keep-alive 缓存的组件激活时调用。
- deactivated:被 keep-alive 缓存的组件失活时调用。生命周期钩子
mounted拿到数据后可以直接获取dom吗
mounted只是在组件实例挂载的时候执行,数据改变不会再次执行。所以只会执行一次。
nextTick原理
将回调推迟到下一个 DOM 更新周期之后执行。在更改了一些数据以等待 DOM 更新后立即使用它。他会等到组件的所有子组件也加载完毕后执行的。
使用场景:想要操作基于最新数据的生成DOM时,就将这个操作放在 nextTick 的回调中。例如计算图片加载后的高度,然后计算图片下方元素的位置。
将传入的回调函数包装成异步任务,异步任务又分微任务和宏任务,为了尽快执行所以优先选择微任务。
源码位置:core\packages\runtime-core\src\scheduler.ts
vue模板(template)里为什么不能使用多个头结点?
这个是值多个根节点吗?
因为非props的attrs挂载会出现错误。
vuex为什么同时设计mutation和action?只设计一个行不行?
- mutation: 处理同步数据改变
在mutation里面加入了异步处理的函数。其实mutation是可以正常使用的,但是我们在日常的开发中debug的时候,我们需要查看devtool中的mutation日志。
理论上来说,是mutation走一步,devtool记录一步,但是在mutation中加入异步函数就会导致我们devtool的记录失败,因为devtool不知道你里面的异步函数什么时候调用,在哪里调用。
- action:处理异步数据的变化。
不行,因为 vue dev-tools不能追踪到异步数据的变化。
vue2和 vue3 在数据绑定这一块有什么区别?
- vue2通过Object.defineProperty
- vue3通过Proxy
重学vue(2, 3)及其生态+TypeScript 之 vue部分实现和源码分析
vue挂载和卸载父子组件生命周期钩子执行顺序