[英]Weird behaviour of methods in Vue.js
我的应用程序中有一个data
变量,它是message
,而且我在执行某些加密算法的方法中有一种方法。 这是我的代码。
export default {
data: () => ({
message: ""
}),
methods: {
click() {
this.message = "Hello";
console.log("this.message ", this.message); // Prints "Hello"
// takes around 8 seconds
var encryptedPassphrase = generateKeystore();
console.log("this.message ", this.message); // Prints "Hello"
}
}
};
我在 HTML 标记中显示的message
变量上方,并且方法click
从 Vuetify 按钮调用。 下面是HTML代码,
<div>
<p>{{message}}</p>
<v-btn @click="click">Click</v-btn>
</div>
问题
现在的问题是当click
方法被调用时,它所做的第一个任务是更新message
变量,但是这个message
变量更新会在完整的函数执行完成后反映在 HTML 中。 因此,在click
功能中,下一个任务是加密计算,大约需要 8 秒,完成后message
会反映在 HTML 中。 我不知道这里发生了什么。 只是提到我在这里使用webpack
。
<v-btn @click="update(); click();">Click</v-btn>
即使这样也不起作用,这里的update
方法会更新message
变量,它会在click
功能完成后更新。
如果您希望 click 方法中更改的消息数据字段在方法完成之前反映在 html 中,则必须将加密函数包装在Vue.nextTick
中。 这将确保nextTick
内部的逻辑将在下一个DOM
更新周期执行。 这将允许使用消息的最新值更新DOM
,然后它将执行加密功能。 否则, Vue
将等待 click 函数完成,然后再将更改反映在DOM
中。
Vue.nextTick(function() { //cryptographic function })
长话短说,在这种情况下,您应该将Web Worker用于密集型任务,例如您的generateKeystore
函数。 您的message
没有被渲染的原因是一次只执行了一段 Javascript,基本上您的generateKeystore
会阻止 Vue 渲染(观察器等),直到它完成。
我创建了一个 js fiddle 来演示 Vue - Web Worker 的用法https://jsfiddle.net/Fourzero/t9L1g2hj/17/ 。 您还可以在下面找到代码。 在此示例中, click
处理程序具有您描述的相同问题(更改的消息在慢速函数完成之前不会呈现), click2
方法以立即呈现message
“你好”的方式处理它,并且慢速函数启动执行(需要几秒钟)并在完成后返回值。
<script id="worker1" type="javascript/worker">
// This script won't be parsed by JS engines because its type is javascript/worker.
self.onmessage = function(e) {
console.log('slow function started execution inside worker with parameter: ', e.data)
// execute slow function
var sum = 1;
for (let i = 1; i < 10000000000; i++) {
sum = sum + i;
}
console.log('DONE!!slow function finished inside worker with result: ' + sum)
self.postMessage(sum);
};
</script>
<div id="app">
<p ref="message">{{message}}</p>
<p >slowFunctionResult: {{slowFunctionResult}}</p>
<button @click="click">Click</button>
<button @click="click2">Click (Run in worker)</button>
</div>
var blob = new Blob([
document.querySelector('#worker1').textContent
], { type: "text/javascript" })
// Note: window.webkitURL.createObjectURL() in Chrome 10+.
var worker = new Worker(window.URL.createObjectURL(blob));
new Vue({
el: '#app',
data: {
message: 'xx',
slowFunctionResult: ''
},
methods: {
click() {
this.message = 'hello';
console.log("slow function start")
this.slowFunction();
console.log("slow function done")
// the next tick won't happen until the slow function finished
},
click2() {
this.message = 'hello';
let that = this;
worker.onmessage = function(e) {
console.log("Received result from worker!: " + e.data);
that.slowFunctionResult = e.data;
}
// DOM should be updated before the slow function execution finished
worker.postMessage(this.message); // Start the worker.
},
slowFunction() {
var sum = 1;
for (let i = 1; i < 10000000000; i++) {
sum = sum + i;
}
}
}
})
单击Click (Run in worker)
按钮的控制台输出
slow function started execution inside worker with parameter: hello
// after a few seconds
DONE!!slow function finished inside worker with result: 49999999990067860000
Received result from worker!: 49999999990067860000
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.