簡體   English   中英

Vue.js 中方法的奇怪行為

[英]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 })

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

長話短說,在這種情況下,您應該將Web Worker用於密集型任務,例如您的generateKeystore函數。 您的message沒有被渲染的原因是一次只執行了一段 Javascript,基本上您的generateKeystore會阻止 Vue 渲染(觀察器等),直到它完成。

我創建了一個 js fiddle 來演示 Vue - Web Worker 的用法https://jsfiddle.net/Fourzero/t9L1g2hj/17/ 您還可以在下面找到代碼。 在此示例中, click處理程序具有您描述的相同問題(更改的消息在慢速函數完成之前不會呈現), click2方法以立即呈現message “你好”的方式處理它,並且慢速函數啟動執行(需要幾秒鍾)並在完成后返回值。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM