vue 组件第一次不渲染问题_Vue 动态组件渲染问题分析

本文深入分析了Vue中动态组件在首次渲染时可能出现的问题,具体表现为无论切换按钮,始终显示为初始组件。问题源于Vue的构造器和数据合并策略,导致在动态切换时未能正确创建子组件实例。解决方案包括传递构造器而不是对象,或利用方法避免数据合并冲突。适合有一定基础的Vue开发者阅读。

fire

读在最前面:

1、本文适用于有一定基础的vue开发者,需要了解基本的vue渲染流程

2、本文知识点涉及vue构造器以及选项策略合并、 渲染逻辑

问题描述:

Child继承自App,主程序通过true 和false来控制显示 Child 还是 App,在动态 中渲染出来的始终是App,代码如下

Vue.config.productionTip = false;

Vue.config.devtools = false;

// ----------------options---------------------

const optionsA = {

render: (h) => h('span', '我是options - 父'),

};

const optionsB = {

render: (h) => h('span', '我是options - 子'),

};

const App = Vue.extend({

template: `

当前组件: {{name}}

`,

data() {

return {

name: 'App',

node: optionsA,

}

}

});

const Child = App.extend({

name: 'Child',

data() {

return {

name: 'Child',

node: optionsB,

}

}

});

const vm = new Vue({

el: '#app',

data() {

return {

isSuper: true,

};

},

components: { App, Child },

render(h) {

const that = this;

return h('div', {}, [

h('button', {

on: {

click: () => {

this.isSuper = true;

}

},

}, '父类'),

h('button', {

on: {

click: () => {

this.isSuper = false;

}

},

}, '子类'),

h(this.isSuper ? 'App' : 'Child')

]);

},

});

如下图(点击父/子类切换,始终显示的是 父文本):

关键执行顺序分析:

1、App通过继承Vue生成构造,Child通过继承App生成构造

2、默认isSuper:true,渲染出App( 编译为render: _C(node),这个时候会在App的node中生成.Ctor)

3、切换isSuper:false,渲染出Child(这里渲染的时候,生成的实例是App,这里是不符合预期的,按理应该是Child)

3.1、生成Child实例的时候进行了data合并,这个时候data中node变量合并了App的node中的.Ctor($options合并策略),参照下图

3.2、在_createElement的时候 node 当为component options / constructor 时,会验证是否 node 是否为object,如果是会转换为构造器 使用vue.extend

3.2、在Child中动态调用 new Ctor() (这个Ctor是App的),生成实例

最后附上大致流程图:

备注:

1、Vue.extend会生成VueComponent构造器,内部包含一个Ctor,组件生成的时候就是调用这个new Ctor() 进行实例生成

2、选项中data的生成是延迟到实例生成的时候

3、createComponent在分支渲染时,传入Ctor为对象的时候,会转换为构造器,这也是我们这个使用 const optionsA = {render: (h) => h('span', '我是options - 父'), }; 这种方式的问题根源所在

4、知道了问题所在,解决方式就比较多了,比如直接传入构造器,比如绕开data值合并策略,使用method方式。

by:海豚湾-丰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值