title: Vue渲染父子组件时需要注意的点
date: 2018-11-19 18:55:58
tags: [Vue]
categories: Vue
前言
我在边学 Vue 边做 轱辘UI 的项目中,写 row 组件 的测试用例时碰到了一个问题。
测试用例需要渲染两个组件,它们是父子关系,但测试下来子组件并没有拿到父组件的 gutter 属性,发现原来是因为 Vue 异步的渲染。
之后通过 setTimeout 和 done() 解决了这一问题,之后便有了这篇博客。
分析
Vue到底是怎样渲染组件到页面的?看例子来分析吧
我们自己会怎么写:
// 这是个同步的过程
var div = document.createElement('div')
document.body.appendChild(div)
而 Vue 不是这么简单的:
var div = document.createElement('div')
var child = document.createElement('div')
// 步骤一,会触发child的mounted事件,这是异步的
div.appendChild(child)
// 步骤二,会触发div的mounted事件,这也是异步的
document.body.appendChild(div)
// 步骤三,这行代码会先于上面两行执行,因为这是同步的,而此时div里还没有child
console.log(div.outerHTML)
执行顺序:步骤三 → 步骤一 → 步骤二
Vue 钩子的调用并不是同步的。
假如是同步的,mounted你写了几百行代码,则需要大量的运算,那Vue岂不是要等你执行完再继续?
所以 Vue 不应该等,Vue 应该优先完成元素的渲染,这是一个异步的触发
解决
我预想子组件会通过 mounted 钩子拿到父组件传来的 gutter 属性,但我的测试用例执行时,实际上还没有执行 mounted 钩子,所以子组件才没有拿到这个 gutter 属性的值。
知道了原因,那么就好解决了,用 setTimeout(){}
另外由于测试框架默认都是同步的代码(这是测试框架的一个约定),所以要在参数中加上 done ,在我的测试用例执行完时调用 done()。
这样,就解决了。具体代码可在此点击 。