Vue.js 中方法的奇怪行为

Posted

技术标签:

【中文标题】Vue.js 中方法的奇怪行为【英文标题】:Weird behaviour of methods in Vue.js 【发布时间】:2019-06-16 14:47:54 【问题描述】:

我的应用程序中有一个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"
    
  
;

message 变量上方我在 html 标记中显示,并且方法 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函数完成后更新。

【问题讨论】:

你有什么可重现或可验证的例子/小提琴我们可以修补吗? 我可以,但问题是我无法在小提琴中运行该加密函数,这需要更多时间来执行。 :( 也许可以尝试将加密函数包装在 Promise 中并异步执行。 无效,方法执行完成后更新。 【参考方案1】:

长话短说,在这种情况下,您应该将Web Worker 用于密集任务,例如您的generateKeystore 函数。你的message 没有被渲染的原因是一次只执行了一段javascript,基本上你的generateKeystore 会阻止Vue 渲染(观察者等)直到它完成。

我创建了一个 js fiddle 来演示 Vue - Web Worker 的用法https://jsfiddle.net/Fourzero/t9L1g2hj/17/。您还可以在下面找到代码。在此示例中,click 处理程序具有与您描述的相同的问题(更改的消息在慢速函数完成之前不会呈现),click2 方法以message 'hello' 立即呈现的方式处理它,并且慢速函数开始执行(需要几秒钟),完成后将返回值。

HTML

<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>

Javascript

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

【讨论】:

【参考方案2】:

如果您希望在 click 方法中更改的消息数据字段在方法完成之前反映在 html 中,您必须将加密函数包装在 Vue.nextTick 中。这将确保nextTick 中的逻辑将在下一个DOM 更新周期执行。这将允许DOM 更新为消息的最新值,然后它将执行加密功能。否则,Vue 将等待单击功能完成,然后更改才会反映在 DOM 中。

Vue.nextTick(function() //cryptographic function )

https://vuejs.org/v2/api/#Vue-nextTick

【讨论】:

它不起作用,According to this answer nextTick 不是这个用例,nextTick 用于在浏览器呈现之前更新变量,它执行一些任务nextTick 回调。

以上是关于Vue.js 中方法的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

NSArrayController 的奇怪行为

Python元类的__new__方法中的奇怪行为[重复]

VBA 中 Scripting.Dictionary 类的 .item() 方法的奇怪行为

异步程序未异步运行的奇怪行为

triangulatePoints() 方法的奇怪行为

UIViewController 的视图奇怪的调整大小行为