Vue3.0中的reactive


Vue3.0中的reactive

  • reactive 是 Vue3 中提供的實現響應式數據的方法。
  • 在 Vue2 中響應式數據是通過 defineProperty 來實現的,
  • 在 Vue3 中響應式數據是通過 ES6 的 Proxy來實現的。
  • reactive 參數必須是對象 (json / arr)
  • 如果給 reactive 傳遞了其它對象
    • 默認情況下,修改對象無法實現界面的數據綁定更新。
    • 如果需要更新,需要進行重新賦值。(即不允許直接操作數據,需要放個新的數據來替代原數據)
reactive 使用基本類型參數

基本類型(數字、字符串、布爾值)在 reactive 中無法被創建成 proxy 對象,也就無法實現監聽。

<template>
<div>
  <p>{{msg}}</p>
  <button @click="c">button</button>
</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    let msg = reactive(0)
    function c() {
      console.log(msg);
      msg ++;
    }
    return {
      msg,
      c
    };
  }
}
</script>

08utpj.png

點擊 button ,我們期望的結果是數字從 0 變成 1,然而實際上界面上的數字並沒有發生任何改變。

查看控制台,它的輸出是這樣的(我點了 3 次)

08uN1s.png

出現提示

value cannot be made reactive: 0

而輸出的值確實發生了變化,只不過這種變化並沒有反饋到界面上,也就是說並沒有實現雙向數據綁定。當然,如果是 ref 的話,就不存在這樣的問題。而如果要使用 reactive ,我們需要將參數從 基本類型 轉化為 對象。

<template>
<div>
  <p>{{msg.num}}</p>
  <button @click="c">button</button>
</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    let msg = reactive({
      num: 0
    })
    function c() {
      console.log(msg);
      msg.num ++;
    }
    return {
      msg,
      c
    };
  }
}
</script>

將參數替換成了對象 {num: 0},此時,點擊按鈕界面就會產生改變(我點了 3 次)。

08u8AS.png

在控制台打印消息

08uGtg.png

可以看到,msg 成功被創建成了 proxy 對象,他通過劫持對象的 getset 方法實現了對象的雙向數據綁定。

深層的、對象內部的變化也能被察覺到(注意下面代碼中的 inner

<template>
<div>
  <p>{{msg.num.inner}}</p>
  <button @click="c">button</button>
</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    let msg = reactive({
      num: {
        inner: 0
      }
    })
    function c() {
      console.log(msg);
      msg.num.inner ++;
    }
    return {
      msg,
      c
    };
  }
}
</script>

08uJhQ.png

數組變化也不在話下。

<template>
<div>
  <p>{{msg}}</p>
  <button @click="c">button</button>
</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    let msg = reactive([1, 2, 3])
    function c() {
      console.log(msg);
      msg[0] += 1;
      msg[1] = 5;
    }
    return {
      msg,
      c
    };
  }
}
</script>

08uUcn.png

在-reactive-使用-date-參數在 reactive 使用 Date 參數

如果參數不是數組、對象,而是稍微奇怪一點的數據類型,例如說 Date ,那么麻煩又來了。

<template>
<div>
  <p>{{msg}}</p>
  <button @click="c">button</button>
</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    let msg = reactive(new Date())
    function c() {
      console.log(msg);
      msg.setDate(msg.getDate() + 1);
      console.log(msg);
    }
    return {
      msg,
      c
    };
  }
}
</script>!

08uwn0.png

這里我先打印了 msg 兩次,可以看到,點擊一次 button ,msg 的數據是存在變化的,但界面並未發生變化,同時我們發現在控制台里,msg 並未被識別成 proxy

就算我們把 Date 放在對象里,就像這樣

<template>
<div>
  <p>{{msg.date}}</p>
  <button @click="c">button</button>
</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    let msg = reactive({
      date: new Date()
    });
    function c() {
      console.log(msg);
      msg.date.setDate(msg.date.getDate() + 1);
      console.log(msg);
    }
    return {
      msg,
      c
    };
  }
}
</script>

也仍然不起效果。

08u0BV.png

08uB7T.png

顯然,對於這種數據類型,我們需要做特殊處理。

這個特殊處理就是重新賦值(,而不是直接修改原來的值)。

<template>
<div>
  <p>{{msg.date}}</p>
  <button @click="c">button</button>
</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    let msg = reactive({
      date: new Date()
    });
    function c() {
      console.log(msg);
      msg.date.setDate((msg.date.getDate() + 1));
      msg.date = new Date(msg.date);
      console.log(msg);
    }
    return {
      msg,
      c
    };
  }
}
</script>

這里我采用了拷貝的方案重新賦值了 msg.date,界面成功發生了變化(日期 + 1)。

08urAU.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM