vue强制刷新组件_如何强制vue组件重新渲染

本文介绍了在Vue中如何强制组件重新渲染,包括使用`:key`属性、`v-if`和`$forceUpdate()`方法。详细讨论了每个方法的工作原理,以及何时使用它们。特别强调了使用`:key`是最佳实践,因为其他方法可能会导致不必要的组件销毁和重建。
摘要由CSDN通过智能技术生成

【不完全翻译系列】

有些时候vue的响应机制并不起作用(注:vue官网文档 注意事项),这个时候我们需要强制vue组件重新渲染,也或许你可以删掉当前的组件重新创建一个新组件。所以,如何才能正确地让组件重新渲染?

最好的方法是给组件设置 :key ,当你需要组件重新渲染时,只需要更改key的值。

除了用key外,用的比较多的还有另外两种方法:

用v-if

用组件的forceUpdate方法

v-if

如我们将renderComponent赋值给v-if指令:

App.vue

export default {

components: { MyComponent },

data() {

return {

renderComponent: true

};

},

methods: {

forceRerender(){

this.renderComponent = false;

this.$nextTick().then(()=>{

this.renderComponent = true;

});

}

},

mounted(){

this.forceRerender();

}

};

复制代码

MyComponent.vue

Child Component

mounted(){

window.console.log('mounted');

},

beforeDestroy(){

window.console.log('before destroied');

}

};

复制代码

用vue cli3的快速原型方法build,你会看到控制台输出如下:

mounted

before destroied

mounted

复制代码

第一个是正常mount,后面的before destroied,然后又mounted是因为我们改变了renderComponent。所以v-if会让组件重新开始一个生命周期。

关于nextTick:一个tick是指DOM的一个更新周期。vue会在一个周期内收集所有更新,到周期结束时vue会根据收集的更新来重新渲染DOM。上面的代码,如果我们不等到下一个tick就更新renderComponent,实际上只是将renderComponent的值还原了,因为在周期的末尾vue会认为renderComponent的值没有改变,而不会重新渲染MyComponent。

In Vue, a tick is a single DOM update cycle. Vue will collect all updates made in the same tick, and at the end of a tick it will update what is rendered into the DOM based on these updates. If we don't wait until the next tick, our updates to renderComponent will just cancel themselves out, and nothing will change.

forceUpdate

正常情况下,改变数据vue重新渲染组件。但当你调用forceUpdate时,即时没有数据改变,组件也会重新渲染。

如果改变数据,vue会自动重新渲染,那我们为什么需要强制重新渲染?

当然大部分时候是不需要我们强制组件重新渲染的。只是在某些情况下vue的响应式机制会无法处理,具体哪些情况可以参考:注意事项

我们修改MyComponent.vue

Child Component

{{numbers.toString()}}

data(){

return {

numbers:[1,2,3]

}

},

mounted(){

window.console.log('mounted');

this.numbers[this.numbers.length] = 4; // (A)

this.$forceUpdate();

},

beforeDestroy(){

window.console.log('before destroyed');

}

};

复制代码

通过直接给数组索引位置赋值,是不会触发vue自动渲染的。所以后面我们可以调用forceUpdate方法重新渲染组件。这种方法一般不会用到,如果你的代码中用到了这样的更新数据方法,那就需要检查你的代码了。

还有就是forceUpdate方法只会重新调用组件的render方法,不会销毁组件重新渲染。就是说只是重新跑了一次组件更新流程,其他的生命周期钩子不会重新执行。这里有尤大的原话

$forceUpdate only force the view to re-render, not the computed properties. Your computed property should not contain an external non-reactive variable (time), which makes it impure.

Key

key的作用主要是让vue知道某个组件是由某块数据渲染的,让数据跟对应的组件有种唯一的对应关系。通过key,vue可以知道哪些数据变了,哪些没有变。如果key不变,vue将不会重新渲染组件;如果key改变了,vue会销毁旧的组件重新创建一个。

先来说说vue里面为什么需要key。

假如我们要渲染以下数组:

const people = [

{ name: 'Evan', age: 34 },

{ name: 'Sarah', age: 98 },

{ name: 'James', age: 45 }

];

复制代码

我们用数组索引作为key,具体如下:

  • {{ person.name }} - {{ index }}

// Outputs

Evan - 0

Sarah - 1

James - 2

复制代码

现在假如我们删除Sarah,输出:

Evan - 0

James - 1

复制代码

vue会发现key为0的Evan没变,key为1的原来是Sarah,现在是James,所以认为key为1处的数据变了,vue会重新渲染James,然而James实际是没有改变的,这误导了vue。实际上当Sarah被删除时,vue会删除Sarah和James各自对应的组件,然后重新创建一个James对应的组件。

所以某些时候用index作为key是有问题的,我们需要一个唯一的键值(通常是id)来表示key。接下来修改代码如下:

const people = [

{ id: 'this-is-an-id', name: 'Evan', age: 34 },

{ id: 'unique-id', name: 'Sarah', age: 98 },

{ id: 'another-unique-id', name: 'James', age: 45 },

];

  • {{ person.name }} - {{ person.id }}

复制代码

现在vue通过不同的id关联两个不同的组件,当你删除一个时,vue会删除对于的组件,而不会影响到其他。如果我们增加一项数据到数组,同样不会影响其他组件,vue会根据所增加的数据创建一个新的组件与之关联,并将其插入正确的地方。

最好我们修改App.vue的代码,改为key的方式:

export default {

components: { MyComponent },

data() {

return {

componentKey: 0

};

},

methods: {

forceRerender(){

this.componentKey += 1;

}

},

mounted(){

this.forceRerender();

}

};

复制代码

请记住,如果你发现你需要强制重新渲染一个组件,那么可能你的实现不是最好的方法。如果确实需要强制重新渲染组件,那就选择用key的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值