Vue3快速上手

Vue3-admin 快速上手實(shí)戰(zhàn)項(xiàng)目

1、vue3中全部采用函數(shù)式寫法,替換了原來(lái)類的寫法,

2、移除了原有的生命周期函數(shù),和data、computed、watch、method等vue2中的對(duì)象,去掉了this, 并且去除了過(guò)濾器api -> filter

3、vue3源碼全部采用ts編寫,編碼中實(shí)現(xiàn)了對(duì)ts更好的支持

4、vue3完全兼容vue2,在vue3中依然可以按照vue2的方式去寫代碼,而且兩種寫法可以同時(shí)存在,

5、組件中同時(shí)存在兩種寫法時(shí),當(dāng)setup返回值中定義的方法和methods中的方法同名時(shí),會(huì)拋出錯(cuò)誤。
定義的數(shù)據(jù)和data定義的數(shù)據(jù)字段相同時(shí),會(huì)被data定義的字段覆蓋

6、vue3采用proxy的方式實(shí)現(xiàn)數(shù)據(jù)代理,只會(huì)代理第一層數(shù)據(jù) 避免了vue2中對(duì)data的深層遞歸,提升了組件渲染性能

如下所示:

// 在vue3中定義一個(gè)響應(yīng)式數(shù)據(jù)

const state = reactive({data: {obj: {}}});

state.data.obj = xxx;

返回的state是一個(gè)proxy對(duì)象,默認(rèn)只會(huì)對(duì)data進(jìn)行代理
那么vue3是怎么實(shí)現(xiàn)深層數(shù)據(jù)劫持呢,例如我們要修改obj那么是怎么監(jiān)聽到obj的修改呢

當(dāng)我們要對(duì)深層對(duì)象obj進(jìn)行修改時(shí),會(huì)調(diào)用 state.data 的get方法,在get方法中會(huì)對(duì)state.data 進(jìn)行代理,劫持state.data中的屬性, get方法返回的不是state.data本身,而是被proxy代理過(guò)的對(duì)象,從而巧妙的實(shí)現(xiàn)了深層數(shù)據(jù)劫持,在用到該屬性的時(shí)候一定會(huì)調(diào)用父級(jí)的get方法,這時(shí)候才會(huì)去劫持屬性的get和set方法

一、setup函數(shù)

setup函數(shù)是vue3中所有api的入口和出口

vue3中用setup函數(shù)整合了所有的api, setup函數(shù)只執(zhí)行一次,在生命周期函數(shù)前執(zhí)行,所以在setup函數(shù)中拿不到當(dāng)前實(shí)例this,不能用this來(lái)調(diào)用vue2寫法中定義的方法

vue3中去掉了data,使用setup的返回值來(lái)給模板綁定value

return 的對(duì)象如果是常量,不會(huì)變成響應(yīng)式數(shù)據(jù)

this.$emit 用 context.emit 方法來(lái)替代

// props - 組件接受到的屬性, context - 上下文 
setup(props, context){
    return {
        // 要綁定的數(shù)據(jù)和方法
    }
}

二、生命周期

生命周期函數(shù),都變成了回調(diào)的形式,寫在setup函數(shù)中
可以一次寫多個(gè)相同的生命周期函數(shù),按照注冊(cè)順序執(zhí)行

setup() {
    onMounted(() => {
      console.log('組件掛載1');
    });
    
    onMounted(() => {
      console.log('組件掛載2');
    });

    onUnmounted(() => {
      console.log('組件卸載');
    });

    onUpdated(() => {
      console.log('組件更新');
    });

    onBeforeUpdate(() => {
      console.log('組件將要更新');
    });

    onActivated(() => {
      console.log('keepAlive 組件 激活');
    });

    onDeactivated(() => {
      console.log('keepAlive 組件 非激活');
    });

    return {};
  },

三、ref - 簡(jiǎn)單的響應(yīng)式數(shù)據(jù)

1、ref可以將某個(gè)普通值包裝成響應(yīng)式數(shù)據(jù),僅限于簡(jiǎn)單值,內(nèi)部是將值包裝成對(duì)象,再通過(guò)defineProperty來(lái)處理的
通過(guò)ref包裝的值,取值和設(shè)置值的時(shí)候,需用通過(guò)value來(lái)進(jìn)行設(shè)置

2、可以用ref來(lái)獲取組件的引用,替代this.$refs的寫法

<template>
  <div class="mine">
    <input v-model="inputVal" />
    <button @click="addTodo">添加</button>
    <ul>
      <li v-for="(item, i) in todoList" :key="i">
        {{ item }}
      </li>
    </ul>
  </div>
  <div></div>
</template>


setup() {
    const inputVal = ref('');
    const todoList = ref<string[]>([]);

    function addTodo() {
      todoList.value.push(inputVal.value);
      inputVal.value = '';
    }

    return {
      addTodo,
      inputVal,
      todoList,
    };
  },

四、reactive - 數(shù)據(jù)綁定

使用reactive來(lái)對(duì)復(fù)雜數(shù)據(jù)進(jìn)行響應(yīng)式處理,它的返回值是一個(gè)proxy對(duì)象,
在setup函數(shù)中返回時(shí),可以用toRefs對(duì)proxy對(duì)象進(jìn)行結(jié)構(gòu),方便在template中使用

通過(guò)reactive來(lái)創(chuàng)建響應(yīng)式數(shù)據(jù)data,用toRefs來(lái)進(jìn)行解構(gòu),在模板中直接使用 inputVal、todoList

模板中綁定的方法也需要 在setup函數(shù)中定義,并返回,才能綁定到模板中,例如addTodo方法

vue3模板: 一個(gè)templage可以有多個(gè)平級(jí)的標(biāo)簽(vue2中只能在template寫一個(gè)子標(biāo)簽)

<template>
  <div class="mine">
    <input v-model="inputVal" />
    <button @click="addTodo">添加</button>
    <ul>
      <li v-for="(item, i) in todoList" :key="i">
        {{ item }}
      </li>
    </ul>
  </div>
  <div></div>
</template>

setup() {
    const data = reactive({
      inputVal: '',
      todoList: [],
    });

    function addTodo() {
      data.todoList.push(data.inputVal);
      data.inputVal = '';
    }

    return {
      ...toRefs(data),
      addTodo,
    };
  },


五、 computed

計(jì)算屬性,變成了函數(shù)寫法,當(dāng)依賴的值發(fā)生改變時(shí)會(huì)重新計(jì)算
computed包裝后的值,需要用 .value去取值,template中不需要使用.value。

async setup() {
    const data = reactive({
      a: 10,
      b: 20,
    });
    
    let sum = computed(() => data.a + data.b);

    return { sum };
  },

六、 watch

變成了函數(shù)寫法,與vue2中用法相同

// 偵聽一個(gè)
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
)

// 直接偵聽一個(gè)ref
const count = ref(0)
watch(count, (count, prevCount) => {
  /* ... */
})

七、watchEffect 新增方法

響應(yīng)式地跟蹤函數(shù)中引用的響應(yīng)式數(shù)據(jù),當(dāng)響應(yīng)式數(shù)據(jù)改變時(shí),會(huì)重新執(zhí)行函數(shù)

const count = ref(0)
// 當(dāng)count的值被修改時(shí),會(huì)執(zhí)行回調(diào)
watchEffect(() => console.log(count.value))

八、 vue-router

組件中使用路由時(shí)用useRoute和useRouter

import {useRoute, useRouter} from 'vue-router'

const route = useRoute(); // 相當(dāng)于 vue2 中的this.$route
const router = useRouter(); // 相當(dāng)于 vue2 中的this.$router

route   用于獲取當(dāng)前路由數(shù)據(jù)
router  用于路由跳轉(zhuǎn)

九、 vuex

使用useStore來(lái)獲取store對(duì)象
從vuex中取值時(shí),要注意必須使用computed進(jìn)行包裝,這樣vuex中狀態(tài)修改后才能在頁(yè)面中響應(yīng)

import {useStore} from 'vuex'

setup(){
    const store = useStore(); // 相當(dāng)于 vue2中的 this.$store
    store.dispatch(); // 通過(guò)store對(duì)象來(lái)dispatch 派發(fā)異步任務(wù)
    store.commit(); // commit 修改store數(shù)據(jù)
    
    let category = computed(() => store.state.home.currentCagegory
    return { category }
}

十、用jsx來(lái)定義vue組件

vue3中支持使用jsx語(yǔ)法來(lái)定義vue組件

export const AppMenus = defineComponent({
  setup() {

    return () => {
      return (
        <div class="app-menus">
          <h1>這是一個(gè)vue組件</h1>
        </div>
      );
    };
  },
});

十一、插槽修改


<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

一個(gè)不帶 name 的 <slot> 出口會(huì)帶有隱含的名字“default”。

在向具名插槽提供內(nèi)容的時(shí)候,我們可以在一個(gè) <template> 元素上使用 v-slot 指令,并以 v-slot 的參數(shù)的形式提供其名稱,也可以使用v-slot的簡(jiǎn)寫方式#, v-slot:header等價(jià)于 #header

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>

  <template #footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

十二、Suspense 和 異步 setup

    <Suspense>
        <template #default>
          <home-swiper></home-swiper>
        </template>
        <template #fallback>
          <div>loading...</div>
        </template>
    </Suspense>

組件的setup方法使用異步,頁(yè)面在加載時(shí)會(huì)先顯示 fallback內(nèi)容,當(dāng)setup函數(shù)執(zhí)行完畢才會(huì)正常加載 home-swiper組件

async setup() {
    let store = useStore();
    let sliderList = computed(() => store.state.home.sliders);
    // 計(jì)算屬性,需要多加 .value
    if (sliderList.value.length === 0) {
      // 緩存 如果沒有數(shù)據(jù),請(qǐng)求接口獲取
      await store.dispatch(`home/${Types.SET_SLIDER_LIST}`);
    }

    return { sliderList };
  },

Vue3-admin 快速上手實(shí)戰(zhàn)項(xiàng)目

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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