GithubHelp home page GithubHelp logo

issueslistofvue's People

Contributors

sfsoul avatar

Stargazers

 avatar

Watchers

 avatar

issueslistofvue's Issues

Vue 采用异步渲染的原因

异步渲染:异步更新队列指的是当状态发生变化时,Vue 异步执行DOM的更新。

场景

在日常项目开发中会遇到一种场景:当我们修改某个属性值后,往往想获得更新后的DOM值,但此时通过 $refs 获取到的DOM的值时更新前旧DOM的值,此时需要使用 vm.$nextTick 方法来异步获取DOM。

Vue.component('update-message', {
        template: `
            <button ref="message" @click="updateMessage">{{message}}</button>
        `,
        data () {
            return {
                message: 'Hello world'
            }
        },
        methods: {
            updateMessage () {
                this.message = '哈哈哈';
                console.log(this.$refs.message.textContent);  // 打印message值为:Hello world
                this.$nextTick(() => {
                    console.log('$nextTick', this.$refs.message.textContent);  // 打印message值为:哈哈哈
                })
            }
        }
})

从上面的 demo 可以看到,如果想要在属性值被改变后立刻获取到DOM中的新值,是需要在 vm.$nextTick 的回调中去获取的。

为什么要异步更新视图

<template>
    <div>
        <div>{{test}}</div>
    </div>
</template>
export default {
    data () {
        return {
            test: 0
        };
    },
    mounted () {
      for(let i = 0; i < 1000; i++) {
        this.test++;
      }
    }
}

如上情况:mounted 的时候属性 test 的值会被 ++ 循环执行1000次。每次++时,都会根据响应式触发 setter => Dep => Watcher => update => patch。 如果此时没有异步更新视图,那么每次++都会直接操作DOM更新视图,这是非常消耗性能的。所以Vue实现了一个 queue 队列,在下一个tick的时候会统一执行queue中Watcher的run。同时拥有相同id的Watcher不会被重复加入到该queue中去,所以不会执行1000次Watcher的run。最终更新视图只会直接将test对应的DOM的0变成1000。保证更新视图操作DOM的动作是在当前栈执行完以后下一个tick的时候调用,大大优化了性能。

Vue 同步执行DOM更新的缺点

假设 Vue 是同步执行DOM更新,来看看会存在什么问题?

this.message = '第一个更新';
this.message = '第二个更新';
this.message = '第三个更新';
this.message = '第四个更新';

上面代码修改了4次 message 的值,所以DOM也会更新4次,DOM的更新是十分消耗性能的。 但其实我们真正需要的也就是最后一次更新的结果(即DOM只需要更新一次),前三次的DOM更新是可以省略的。只需要等所有状态都修改好了之后再进行渲染就可以减少一些无用功。

Vue2.0 开始引入 Virtualdom ,每一次状态发生变化后,状态变化的信号会发送给组件,组件内部使用 VirtualDOM 进行计算得出需要更新的具体的DOM节点,然后对DOM进行更新操作,每次更新状态后的渲染过程需要更多的计算,而这种无用功也将浪费更多的性能,所以异步渲染变得更加至关重要。

组件内部使用 VirtualDOM 进行渲染,即组件内部其实不关心哪个状态发生了变化,它只需要计算一次就可以得知哪些节点需要更新。比如说:更改了N个状态,其实只需要发送一个信号就可以将DOM更新到最新啦。

updateStatus () {
    this.name = 'zhangjing';
    this.age = 27;   
}

执行 updateStatus 方法,修改了2种状态,但其实Vue只渲染一次。因为 VirtualDOM 只需要一次就可以将整个组件的DOM更新到最新,它根本不会关心这个更新的信号到底是哪个具体的状态发出来的。

何时进行更新渲染操作

将渲染操作推迟到所有状态都修改完毕后进行。

只需要将渲染操作推迟到本轮事件循环的最后或者下一轮事件循环。即只需要在本轮事件循环的最后,等前面更新状态的语句都执行完之后,执行一次渲染操作,它就可以无视前面各种更新状态的语法,无论前面写了多少条更新状态的语句,只在最后渲染一次即可。将渲染推迟到本轮事件循环的最后,执行渲染的时机会比推迟到下一轮快很多,所以Vue优先将渲染操作推迟到本轮事件循环的最后,如果执行环境不支持会降级到下一轮。

如何避免重复渲染

所谓重复渲染指的是:一个组件属性(以 message 为例)的值被改变多次,那么会有多个对应的任务被添加到任务队列中,应该避免这样

Vue 的变化侦测机制决定了它必然会在每次状态发生变化时都会发出渲染的信号,但Vue会在收到信号之后检查队列中是否已经存在这个任务,保证队列中不会有重复。如果队列中不存在则将渲染操作添加到队列中。 之后通过异步的方式延迟执行队列中的所有渲染的操作并清空队列,当同一轮事件循环中反复修改状态时,并不会反复向队列中添加相同的渲染操作。所以在使用Vue时,修改状态后更新DOM都是异步的。

参考文章

Vue的生命周期

官网图镇楼先:

created

可以理解为是在 observer(data) 方法之后执行的钩子,此时 vm.$data 下的属性都能够被访问到且都已经被数据劫持了。(被添加了 getset

建议做什么

可以调用 ajax 进行一些数据资源的请求,但由于当前生命周期无法通过 $ref 去操作 DOM,
所以有关于请求后需要更新DOM值的操作都放到 mounted 生命周期中。

mounted

实例已经挂载完成,适合去做需要根据获取的数据并去初始化DOM的操作

beforeUpdate

此时DOM中的值并未发生改变,原因在于:虚拟DOM还未重新渲染,且未开始应用更新。 适合在此生命周期中进一步地更改
状态,这不会触发附加的重渲染过程。

updated

可以执行依赖于 DOM 的操作。多数情况下应避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务端渲染
期间不被调用。

beforeUpdate 与 updated 钩子的区别

从下方截图可以很明显的看出来,beforeUpdateupdated 钩子函数的区别在于:DOM节点的值有没有更新。

原因就在于:虚拟DOM的重新渲染以及更新应用的时机是在 beforeUpdate 钩子之后才进行的。

destroyed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.