Vue3 入坑 Chapter 1

Vue3 入坑 Chapter 1

Setup

  1. 新的option, 所有的組合API函數(shù)都在此使用, 只在初始化時執(zhí)行一次
  2. 函數(shù)如果返回對象, 對象中的屬性或方法, 模板中可以直接使用

ref

  1. 作用: 定義一個數(shù)據(jù)的響應(yīng)式

  2. 語法: const xxx = ref(initValue):

    創(chuàng)建一個包含響應(yīng)式數(shù)據(jù)的引用(reference)對象

    js中操作數(shù)據(jù): xxx.value

    模板中操作數(shù)據(jù): 不需要.value

  3. 一般用來定義一個基本類型的響應(yīng)式數(shù)據(jù)

reactive

  1. 作用: 定義多個數(shù)據(jù)的響應(yīng)式
  2. const proxy = reactive(obj): 接收一個普通對象然后返回該普通對象的響應(yīng)式代理器對象
  3. 響應(yīng)式轉(zhuǎn)換是“深層的”:會影響對象內(nèi)部所有嵌套的屬性
  4. 內(nèi)部基于 ES6 的 Proxy 實(shí)現(xiàn),通過代理對象操作源對象內(nèi)部數(shù)據(jù)都是響應(yīng)式的

SetupAPI 示例代碼

<template>
  <div class="SetupAPITest">
    <h3>{{ count }}</h3>
    <button @click="updateCount">更新數(shù)據(jù)</button>
    <hr>
    <h3>姓名: {{ user.name }}</h3>
    <h3>年齡: {{ user.age }}</h3>
    <h3>媳婦: {{ user.wife }}</h3>
    <h3>性別: {{ user.gender }}</h3>
    <button @click="updateUser">更新數(shù)據(jù)</button>
  </div>
</template>

<script lang="ts">
// defineComponent函數(shù), 目的是定義一個組件, 內(nèi)部可以傳入一個配置對象
import { defineComponent, ref, reactive } from 'vue'

// 暴露出去一個定義好的組件
export default defineComponent({
  name: 'SetupAPITest',
  // setup是組合 API 的入口函數(shù)
  setup () {
    // 變量
    /*
    * ref 是一個函數(shù)
    * 作用: 定義一個響應(yīng)式的數(shù)據(jù), 返回的是一個 Ref 對象, 對象中有一個 value 屬性
    *      如果需要對數(shù)據(jù)進(jìn)行操作, 需要使用該 Ref 對象調(diào)用的 value 屬性的方式進(jìn)行數(shù)據(jù)的操作
    * 注意: 在 HTML 模板中不需要使用 .value
    * */
    const count = ref(0)
    /*
    * reactive 是一個函數(shù)
    * 作用: 定義多個數(shù)據(jù)的響應(yīng)式
    *      const proxy = reactive(obj): 接收一個普通對象然后返回該對象的響應(yīng)式代理器對象
    *      響應(yīng)式轉(zhuǎn)換是 "深層次的": 即會影響對象內(nèi)部所嵌套的所有屬性
    *      內(nèi)部是基于 ES6 的 Proxy 實(shí)現(xiàn)的, 通過代理對象操作源對象內(nèi)部數(shù)據(jù)都是響應(yīng)式的
    * 注意: reactive把數(shù)據(jù)變成響應(yīng)式數(shù)據(jù), 返回的是一個 Proxy 的代理對象, 被代理的目標(biāo)對象就是 user 對象
    *      user 現(xiàn)在是代理對象, obj是目標(biāo)對象
    * */
    const obj = {
      name: '小明',
      age: 20,
      wife: {
        name: '小甜甜',
        age: 18,
        cars: ['奔馳', '寶馬', '奧迪']
      }
    }
    const user = reactive<any>(obj)
    // 方法
    function updateCount () {
      count.value++
    }
    const updateUser = () => {
      // 如果直接使用修改目標(biāo)對象的方式來更新目標(biāo)對象中的成員的值, 是不會有響應(yīng)式效果的, 只能使用代理對象的方式去修改
      user.name = '小紅'
      // 在代理對象中, 直接使用 . 的方式就可以新建屬性, 不需要在使用 this.$set()
      user.gender = '男'
      // 刪除屬性
      delete user.age
      /*
      * 總結(jié): 如果操作代理對象, 目標(biāo)對象中的數(shù)據(jù)也會隨之變化, 同時如果想要在操作數(shù)據(jù)的時候, 界面也要重新更新渲染, 也要操作代理對象
      * */

      // 通過當(dāng)前的代理對象找到該對象中的某個屬性, 更改該屬性中的某個數(shù)據(jù), 這種操作以前在 Vue2 中是不可用
      user.wife.cars[1] = '瑪莎拉蒂'

      // 通過當(dāng)前的代理對象把目標(biāo)對象中的某個屬性添加一個新的屬性
      user.wife.cars[3] = '奧拓'
    }
    // 返回的是一個對象
    return {
      count,
      user,
      updateCount,
      updateUser
    }
  }
})
</script>

<style lang="scss" scoped>

</style>

SetupAPI細(xì)節(jié)問題

setup執(zhí)行的時機(jī)
  1. 在beforeCreate之前執(zhí)行(一次), 此時組件對象還沒有創(chuàng)建
  2. this是undefined, 不能通過this來訪問data/computed/methods / props
  3. 其實(shí)所有的composition API相關(guān)回調(diào)函數(shù)中也都不可以
setup的返回值
  1. 一般都返回一個對象: 為模板提供數(shù)據(jù), 也就是模板中可以直接使用此對象中的所有屬性/方法
  2. 返回對象中的屬性會與data函數(shù)返回對象的屬性合并成為組件對象的屬性
  3. 返回對象中的方法會與methods中的方法合并成功組件對象的方法
  4. 如果有重名, setup優(yōu)先
  5. 一般不要混合使用: methods中可以訪問 setup 提供的屬性和方法, 但在 setup 方法中不能訪問 data 和 methods, 一般建議在 setup 中 書寫屬性和方法
  6. setup不能是一個 async 函數(shù): 因?yàn)榉祷刂挡辉偈?return 的對象, 而是promise, 模板看不到 return 對象中的屬性數(shù)據(jù), 所以一般異步請求的方法 要寫在 methods 中
setup的參數(shù)
  1. props參數(shù), 是一個對象, 里面有父級組件向子級組件傳遞的數(shù)據(jù), 并且是在子級組件中使用 props 接收到的所有的屬性

  2. context參數(shù), 是一個對象, 里面有

    attrs對象: 獲取當(dāng)前組件標(biāo)簽上的屬性, 但是該屬性是在 props 中沒有聲明接收的所有的尚需接收的對象, 相當(dāng)于 this.$attrs

    slots對象: 包含所有傳入的插槽內(nèi)容的對象, 相當(dāng)于 this.$slots

    emit對象: 用來分發(fā)自定義事件的函數(shù), 相當(dāng)于 this.$emit

  3. 使用 setup 參數(shù)時的寫法可以寫成

    setup(props, context) 或 setup(props, {attrs, slots, emit})

父組件: SetupAPITest2.vue

<template>
  <div class="SetupAPITest2">
    <h2>APP父級組件</h2>
    msg: {{ msg }}
    <button @click="msg += '==='">更新數(shù)據(jù)</button>
    <hr>
    <child :msg="msg"></child>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
// 引入子組件 Child
import Child from '@/components/Child.vue'

export default defineComponent({
  name: 'SetupAPITest2',
  components: { Child },
  setup () {
    const msg = ref('what are you no sha lei')
    return {
      msg
    }
  }
})
</script>

<style lang="scss" scoped>

</style>

子組件中: Child.vue

<template>
  <div class="child">
    <h2>Child子組件</h2>
    <h3>{{ msg }}</h3>
    <h3>count: {{ count }}</h3>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'child',
  props: ['msg'],
  // 數(shù)據(jù)初始化的生命周期回調(diào)
  beforeCreate () {
    console.log('beforeCreate執(zhí)行了')
  },
  // 界面渲染完畢
  mounted () {
    console.log(this)
  },
  setup (props, context) {
    console.log('setup執(zhí)行了', props, context)

    const showMsg1 = () => {
      console.log('setup中的showMsg1')
    }
    return {
      showMsg1
      // setup中一般都是返回一個對象, 對象中的屬性和方法都可以在 html 模板中直接使用
    }
  },
  data () {
    return {
      count: 10
    }
  },
  methods: {
    showMsg2 () {
      console.log('methods中的showMsg方法')
    }
  }
})
</script>

<style lang="scss" scoped>

</style>

rective 與 ref 的細(xì)節(jié)問題

  1. 使用 ref 處理基本數(shù)據(jù)類型, 使用 rective 處理對象/數(shù)組
  2. 如果用 ref 處理 對象/數(shù)組, 內(nèi)部會自動將 對象/數(shù)組 轉(zhuǎn)換為 reactive 的代理對象
  3. ref內(nèi)部: 通過 value 屬性添加 getter/setter 來實(shí)現(xiàn)對數(shù)據(jù)的劫持
  4. reactive內(nèi)部: 通過使用 Proxy 來實(shí)現(xiàn)對 對象內(nèi)部所有數(shù)據(jù)的劫持, 并通過 Reflect 操作對象內(nèi)部的數(shù)據(jù)
  5. ref的數(shù)據(jù)操作: 在js中要.value, 在模板中不需要(內(nèi)部解析模板時會自動添加.value)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容