vue3學習筆記


在Vue3.0中創建響應式數據需要引用ref,reactive這兩個方法,ref一般用來創建基本數據類型的響應式數據,reactive一般用來創建引用數據類型的響應式數據。
在模板中使用,跟之前沒有區別,需要注意的是,ref屬於將基本類型數據包裝成應用類型,在模板中正常使用。在方法中訪問的時候需要帶上.value才能訪問到。
為什么要這么寫呢?是因為Proxy的原因,Proxy要進行數據劫持的時候需要接收一個對象,所以ref就對基本數據類型的數據進行了包裝,使其可以進行響應式。
 
ref例子:
<template>
  <div>
    {{ count }}
    <button @click="add">+</button>
  </div>
</template>

<script>
import { ref } from "vue";

export default {
  /* 在Vue3.0中創建響應式數據需要引用ref,reactive這兩個方法,ref一般用來創建基本數據類型的響應式數據,reactive一般用來創建引用數據類型的響應式數據。
在模板中使用,跟之前沒有區別,需要注意的是,ref屬於將基本類型數據包裝成應用類型,在模板中正常使用。在方法中訪問的時候需要帶上.value才能訪問到。為什么要這么寫呢?是因為Proxy的原因,Proxy要進行數據劫持的時候需要接收一個對象,所以ref就對基本數據類型的數據進行了包裝,使其可以進行響應式。 */

  name: "Test",
  setup(props, context) {
    const count = ref(0); // 定義響應式數據count
    const objData = {
      name: "erha",
      age: "1",
      skill: "拆家",
    };
    const add = ()=>{
      count.value++;  
    }
    return {
      count,
      add,
    };
  },
};
</script>
由於Proxy的機制原因,如果將reactive中的響應式數據進行解構,那么原先的響應式數據就變成不可響應的了。 
為什么將可觀察對象中的屬性解構出來后,變成不再可觀察了呢?因為通過reactive方法創建的可觀察對象,內部的屬性本身並不是可觀察的,而是通過Proxy代理實現的讀寫觀察,如果將這些屬性解構,這些屬性就不再通過原對象的代理來訪問了,就無法再進行觀察。
Composition API提供了一種方法來解決此機制帶來的問題,那就是toRefs,它可以將reactive創建的可觀察對象,轉換成可觀察的ref對象
當使用了toRefs的時候在模板中只需要使用name即可
<template>
  <div>
    <!-- {{ data.age }} -->
    {{age}}
  </div>
</template>

<script>
import { reactive, toRefs } from "vue";

export default {
  /* 由於Proxy的機制原因,如果將reactive中的響應式數據進行解構,那么原先的響應式數據就變成不可響應的了。 為什么將可觀察對象中的屬性解構出來后,變成不再可觀察了呢?因為通過reactive方法創建的可觀察對象,內部的屬性本身並不是可觀察的,而是通過Proxy代理實現的讀寫觀察,如果將這些屬性解構,這些屬性就不再通過原對象的代理來訪問了,就無法再進行觀察。Composition API提供了一種方法來解決此機制帶來的問題,那就是toRefs,它可以將reactive創建的可觀察對象,轉換成可觀察的ref對象 */
//   當使用了toRefs的時候在模板中只需要使用name即可

  name: "Test",
  setup(props, context) {
    const data = reactive({
      name: "lisa",
      age: 18,
    });
    let { name , age} = toRefs(data)
    // data.age = 20; //響應式
    // age = 30; //非響應式
    data.age = 30; //也是響應式
    return {
    //   data,
    ...toRefs(data)
    };
  },
};
</script>

Composition API提供的computed方法就相當於2.x版本中的計算屬性。使用如下:

<template>
  <div>
    {{ count }}
    {{ doubeCount }}
  </div>
</template>

<script>
import { ref, computed } from "vue";

export default {
  /* Composition API提供的computed方法就相當於2.x版本中的計算屬性。 */

  name: "Test",
  setup(props, context) {
    const count = ref(2);
    const doubeCount = computed(() => {
      return count.value * 2;
    });

    return { count, doubeCount };
  },
};
</script>

Composition API提供的watch方法相當於就是2.x的觀察屬性。

watch方法接收兩個參數,第一個參數是一個函數,第二個參數也是個函數,第一個參數函數返回值表示要監聽哪個數據,第二個參數函數,表示監聽成功后的邏輯,該函數的第一個參數就是監聽到目標數據變化后的值。同時watch可以監聽多個數據。

使用如下:

<template>
  <div class="test">
    <div>watch: count+num:{{ countAddNum }}</div>
    <button @click="addCount">點擊+1</button>
  </div>
</template>

<script>
import { ref, computed, watch } from "vue";
export default {
  /* watch方法接收兩個參數,第一個參數是一個函數,第二個參數也是個函數,第一個參數函數返回值表示要監聽哪個數據,第二個參數函數,表示監聽成功后的邏輯,該函數的第一個參數就是監聽到目標數據變化后的值。同時watch可以監聽多個數據。 */
  name: "Test",
  setup() {
    const count = ref(0); // 定義響應式數據count
    const num = ref(1); // 定義響應式數據num

    const countAddNum = computed(() => {
      // 計算屬性
      return count.value + num.value;
    });
    // 相當於watch
    watch(
      [() => count.value, () => num.value],
      ([count, num], [oldCount, oldNum]) => {
        // watch 同時觀察count和num兩個值
        console.log(
          `count:${count},num:${num} oldCount:${oldCount},oldNum:${oldNum}`
        );
      }
    );
    watch(
      () => {
        return count.value;
      },
      (newcount) => {
        console.log("count變啦", newcount);
      }
    );
    // 相當於methods
    const addCount = () => {
      // 定義增加count方法
      count.value++;
    };

    // 統一return出去
    return {
      count,
      num,
      addCount,
      countAddNum,
    };
  },
};
</script>

 

在Vue2.x版本中頻繁出現的this,在Vue3.0中也消失了,取而代之的是Composition API提供的 getCurrentInstance方法,用來獲取當前組件實例,然后通過ctx獲取當前上下文。
下面是路由跳轉的例子:
<template>
  <button @click="pushRoute">push</button>
</template>

<script>
import { getCurrentInstance } from "vue";

export default {
  name: "Test",
  setup(props, context) {
    const { ctx } = getCurrentInstance();
    console.log(ctx);
    const pushRoute = () => {
      // 編程導航
      ctx.$router.push({
        path: "/",
      });
    };
    return {
      pushRoute,
    };
  },
};
</script>

 

 
 
最后看一下Vue3.0中的生命周期,生命周期也是有所改動,鈎子函數名稱均發生變化。
beforeCreate,created生命周期在 setup方法中自動執行,其余生命周期鈎子函數都是從Vue中引入使用(注意在setup方法中使用)
<template>
  <div>
    <h1>{{ msg }}</h1>
    <div>{{ a }}</div>
    <button @click="setA">加A</button>
  </div>
</template>
<script>
import {
  ref,
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  onErrorCaptured,
  onRenderTracked,
  onRenderTriggered,
} from "vue";
export default {
  setup(props, context) {
    // console.log(props.msg, context)
    const a = ref(0);
    const setA = () => {
      return a.value++;
    };
    // 相當於 beforeMount
    onBeforeMount(() => {
      console.log("onBeforeMount");
    });
    // 相當於 mounted
    onMounted(() => {
      console.log("onMounted");
    });
    // 相當於 beforeUpdate
    onBeforeUpdate(() => {
      console.log("onBeforeUpdate");
    });
    // 相當於 updated
    onUpdated(() => {
      console.log("onUpdated");
    });
    // 相當於 beforeDestroy
    onBeforeUnmount(() => {
      console.log("onBeforeUnmount");
    });
    // 相當於 destroyed
    onUnmounted(() => {
      console.log("onUnmounted");
    });
    onErrorCaptured(() => {
      // 錯誤監控 參考文章 https://zhuanlan.zhihu.com/p/37404624
      console.log("onErrorCaptured");
    });
    onRenderTracked(() => {
      // 已渲染
      console.log("onRenderTracked");
    });
    onRenderTriggered(() => {
      // 當組件更新時會首先觸發此生命周期鈎子 onRenderTriggered->onRenderTracked->onBeforeUpdate->onUpdated
      console.log("onRenderTriggered");
    });
    return {
      a,
      setA,
    };
  },
  name: "HelloWorld",
  props: {
    msg: String,
  },
};
</script>

 參考:https://www.jianshu.com/p/b6ec99ff1cb5


免責聲明!

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



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