[toc]
### 1.$nextTick使用场景
在vue中,如果改变了dom内部绑定的值,立即获取dom的innerHTML,会出现拿到的还是原来的值,这个时候需要用this.$nextTick方法执行回调函数
```js
<div id="app">{{a}}</div>
let vm = new Vue({
el: '#app',
data: {
a: 1
},
mounted() {
this.a = 2
console.log('dom节点内容:', app.innerHTML) // 打印出来的还是1
}
})
```
```js
mounted() {
this.a = 2
this.$nextTick(() => {
console.log('dom节点内容:', app.innerHTML) // 这样打印出来的就是2
})
}
```
### 2.原理
$nextTick当中的操作不会立即执行,而是会等数据、和dom更新之后再执行。
如何实现?
1.$nextTick内部的方法,会被放到一个callbacks数组中
2.当vue中的数据发生更改时,会触发set方法,set会调用dep上的notify方法,通知watcher执行update方法
3.update方法会触发queueWatcher方法,queueWatcher会调用nextTick,并添加一个flushSchedulerQueue方法
4.最后会依次执行callbacks数组中存入的nextTick回调方法,但是这个方法会被promise.then或者Mutation.observer包裹起来,或者setTimeout(根据浏览器是否支持判断),实现了一个异步的调用
```js
update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
this.run()
} else {
queueWatcher(this) // 异步更新逻辑
}
}
```
```js
// queueWatcher
nextTick(flushSchedulerQueue)
```
```js
function flushCallbacks () {
pending = false
const copies = callbacks.slice(0)
callbacks.length = 0
for (let i = 0; i < copies.length; i++) {
copies[i]()
}
}
```
-----
把回调函数放入callbacks等待执行
将执行函数放到微任务或者宏任务中
事件循环到了微任务或者宏任务,执行函数依次执行callbacks中的回调
但是nextTick是同步执行的,同步的把里面的值放到异步队列里了
### 3.watcher去重
```js
this.a = 100
this.a = 200
//代码执行了两次,但是视图只更新了一次
```
因为vue的watcher会去重。
数据发生变化之后,vue的dom并不一定马上发生变化,vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变,如果同一个watcher被多次触发,只会被推入到队列一次。
```js
addDep (dep: Dep) {
const id = dep.id
if (!this.newDepIds.has(id)) {
this.newDepIds.add(id)
this.newDeps.push(dep)
if (!this.depIds.has(id)) {
dep.addSub(this)
}
}
}
```
原理:添加dep的时候,会看这个dep的id,如果已经有了,那么就不会往里面push了
- 0. MVC和MVVM
- 1. v-model无法实时更新的解决办法
- 1. Vue 指令
- 1. v-cloak&v-text&v-html
- 2. v-bind
- 3. v-model
- 7. v-for指令的几种使用方式
- 8. v-if和v-show的使用
- 2. 事件修饰符
- 3. 通过属性设置样式
- 1. 通过属性绑定设置元素class
- 2. 通过属性绑定设置元素style
- 4. 自定义指令
- 11. 自定义全局指令
- 12. 自定义私有指令
- 5. 过滤器
- 6. 键盘指令
- 7. 生命周期
- 8. vue-resource
- 9. 动画
- 1. 使用过渡类名实现动画
- 2. 使用animate.css实现动画
- 3. 钩子函数实现小球半场动画
- 10. 组件
- 1. 全局组件的创建方式
- 2. 私有组件的创建方式
- 3. 组件中的data和methods
- 4. component元素
- 5. 组件配合transition元素实现动画
- 6. 父组件传参传方法
- 11. 路由
- 1. 什么是路由
- 2. vue-router的使用
- 3. 使用router-link&query方式传递参数
- 4. 使用param传值
- 5. 使用children属性实现路由嵌套
- 6. router-view之间获取父级data
- 7. 实现路由跳转的几种方式
- 12. 设置缓存
- 13. $ref 操作DOM&获取自定义属性
- 14. 初始化一个项目
- 15. 使用并封装一个axios方法
- 17. vuex
- 18. watch 监听 data数据
- 19. keep alive 缓存路由组件
- vue效果实现
- 1. 实现顶部根据滑动渐隐渐现
- 2. 制作一个动画包裹组件
- 20. vue 中的数据类操作
- 第三方工具&ui
- 1. vant-ui
- 1. 上拉加载更多
- 2. 使用图片预加载
- 2. better-scroll
- 1. 实现上下滑动效果
- 2. 实现两栏式点击滑动跳转
- vue3
- compositionApi
- 2. ref 和 reactive
- 4. watch
- 5. watchEffect
- 7.使用ref操作dom
- effect副作用
- 1. 新特性
- 3. 生命周期
- 6.定义props
- 实现自定义组件v-model
- vue面试题
- 1.对mvvm的理解
- 2.vue2和vue3响应式数据的理解
- 3.vue中如何检测数组的变化
- 4.vue中如何进行依赖收集
- 5.如何理解vue中的模板编译原理
- 6.vue生命周期以及原理
- 7.vue组件data为什么必须是个函数
- 8.vue-router原理
- 9.vue.mixin原理
- 10.$nextTick原理
- 11.computed和watch的区别
- vue SSR服务端渲染
- 1.什么是服务端渲染
- 2.快速创建服务端渲染