App下載

使用Vue3.0,我收獲了哪些知識(shí)點(diǎn)(一)

猿友 2020-09-07 15:15:58 瀏覽數(shù) (3900)
反饋

這篇文章主要是將自己前期學(xué)習(xí)Vue3.0時(shí)候整理的一些筆記內(nèi)容進(jìn)行了匯總,通過(guò)對(duì)本文的閱讀,你將可以自己完成Vue3.0環(huán)境搭建,同時(shí)還會(huì)對(duì)Vue3.0的一些新的特性進(jìn)行了解,方便自己進(jìn)行Vue3.0的學(xué)習(xí)。

本文所有的示例均使用ant design vue2.0實(shí)現(xiàn),關(guān)于ant design vue2.0請(qǐng)參考 2x.antdv.com/docs/vue/introduce-cn/

初始化環(huán)境

在前面的文章中,我們通過(guò)vite搭建了一個(gè)開(kāi)發(fā)環(huán)境,但是實(shí)際上現(xiàn)在vite并沒(méi)有完善到支撐一個(gè)完整項(xiàng)目的地步,所以本文我們依然選擇使用vue-cli腳手架進(jìn)行環(huán)境搭建。

小編使用的vue-cli版本是4.5.4,如果您的版本比較舊可以通過(guò)npm update @vue/cli來(lái)升級(jí)腳手架版本,如果沒(méi)有安裝可以通過(guò)npm install @vue/cli -g進(jìn)行安裝

使用腳手架新建項(xiàng)目

  1. 在工作空間打開(kāi)終端(cmd),然后通過(guò)vue create my-vue3-test命令初始化項(xiàng)目

  1. 在第一步先選擇Manually select features,進(jìn)行手動(dòng)選擇功能

  1. 然后通過(guò)Space和上下鍵依次選擇

   Choose Vue version
   Babel
   TypeScript
   Router
   Vuex
   CSS Pre-processors
   Linter/Formatter

4.然后回車(chē)

  1. 然后提示選擇Vue版本,選擇3.x(Preview)
  2. Use class-style component syntax?選擇n,即輸入n然后回車(chē)
  3. 然后提示Use Babel alongside TypeScript,輸入y`
  4. Use history mode for router輸入n
  5. 然后css預(yù)處理器選擇Less
  6. eslint選擇ESLint + Prettier
  7. 然后是Lint on saveIn dedicater config files
  8. 最后一路回車(chē)即可完成項(xiàng)目搭建

啟動(dòng)項(xiàng)目

新建完項(xiàng)目之后,進(jìn)入到項(xiàng)目中cd my-vue3-test,然后執(zhí)行 yarn serve即可啟動(dòng)項(xiàng)目

啟動(dòng)之后即可通過(guò)訪問(wèn)http://localhost:8080/訪問(wèn)項(xiàng)目

配置ant design vue

在當(dāng)前Vue3.0正式版還未發(fā)布之際,國(guó)內(nèi)比較出名的前端UI庫(kù)中率先將Vue3.0繼承到自家的UI庫(kù)中的,PC端主要是ant-design-vue,移動(dòng)端主要是vant, 本文所有示例代碼都會(huì)基于ant-design-vue來(lái)進(jìn)行,首先我們先安裝ant-design-vue

  1. 安裝依賴

   yarn add ant-design-vue@2.0.0-beta.6
   yarn add babel-plugin-import -D

  1. 配置ant-design-vue按需加載

進(jìn)入項(xiàng)目根目錄,然后打開(kāi)babel.config.js文件,將里面的內(nèi)容修改為

   module.exports = {
     presets: ["@vue/cli-plugin-babel/preset"],
     plugins: [
       // 按需加載
       [
         "import",
         // style 為 true 加載 less文件
         { libraryName: "ant-design-vue", libraryDirectory: "es", style: "css" }
       ]
     ]
   };

  1. 嘗試使用vue3 + antdv來(lái)添加一個(gè)小頁(yè)面, 我們直接將views/Home.vue文件里面的代碼替換為

<template>
  <a-form layout="inline" :model="state.form">
    <a-form-item>
      <a-input v-model:value="state.form.user" placeholder="Username">
        <template v-slot:prefix
          ><UserOutlined style="color:rgba(0,0,0,.25)"
        /></template>
      </a-input>
    </a-form-item>
    <a-form-item>
      <a-input
        v-model:value="state.form.password"
        type="password"
        placeholder="Password"
      >
        <template v-slot:prefix
          ><LockOutlined style="color:rgba(0,0,0,.25)"
        /></template>
      </a-input>
    </a-form-item>
    <a-form-item>
      <a-button
        type="primary"
        :disabled="state.form.user === '' || state.form.password === ''"
        @click="handleSubmit"
      >
        登錄
      </a-button>
    </a-form-item>
  </a-form>
</template>
<script>
import { UserOutlined, LockOutlined } from "@ant-design/icons-vue";
import { Form, Input, Button } from "ant-design-vue";
import { reactive } from "vue";


export default {
  components: {
    UserOutlined,
    LockOutlined,
    [Form.name]: Form,
    [Form.Item.name]: Form.Item,
    [Input.name]: Input,
    [Button.name]: Button
  },
  setup() {
    const state = reactive({
      form: {
        user: "",
        password: ""
      }
    });


    function handleSubmit() {
      console.log(state.form);
    }


    return {
      state,
      handleSubmit
    };
  }
};
</script>

然后重啟一下項(xiàng)目,就可以發(fā)現(xiàn)已經(jīng)可以正常使用ant-design-vue了。

Vue3.0新體驗(yàn)之setup

對(duì)于Vue3.0的問(wèn)世,最吸引大家注意力的便是Vue3.0Composition API,對(duì)于Componsition API,可以說(shuō)是兩極分化特別嚴(yán)重,一部分人特別喜歡這個(gè)新的設(shè)計(jì)與開(kāi)發(fā)方式,而另一部分人則感覺(jué)使用Composition API很容易寫(xiě)出來(lái)意大利面式的代碼(可能這部分人不知道蘭州拉面吧)。到底Composition API是好是壞,小編不做評(píng)論,反正我只是一個(gè)搬磚的。而本小節(jié)介紹的setup就是Composition API的入口。

setup介紹

setupVue3.0提供的一個(gè)新的屬性,可以在setup中使用Composition API,在上面的示例代碼中我們已經(jīng)使用到了setup,在上文代碼中我們?cè)?code>setup中通過(guò)reactive初始化了一個(gè)響應(yīng)式數(shù)據(jù),然后通過(guò)return返回了一個(gè)對(duì)象,對(duì)象中包含了聲明的響應(yīng)式數(shù)據(jù)和一個(gè)方法,而這些數(shù)據(jù)就可以直接使用到了template中了,就像上文代碼中的那樣。關(guān)于reactive,我將會(huì)在下一小節(jié)為你帶來(lái)說(shuō)明。

setup 的參數(shù)說(shuō)明

setup函數(shù)有兩個(gè)參數(shù),分別是propscontext。

  1. props

propssetup函數(shù)的第一個(gè)參數(shù),是組件外部傳入進(jìn)來(lái)的屬性,與vue2.0props基本是一致的,比如下面代碼

   export  default {
     props: {
       value: {
         type: String,
         default: ""
       }
     },
     setup(props) {
       console.log(props.value)
     }
   }

但是需要注意的是,在setup中,props是不能使用解構(gòu)的,即不能將上面的代碼改寫(xiě)成

   setup({value}) {
       console.log(value)
    }

雖然template中使用的是setup返回的對(duì)象,但是對(duì)于props,我們不需要在setup中返回,而是直接可以在template使用,比如上面的value,可以直接在template寫(xiě)成

   <custom-component :value="value"></custom-component>

  1. context

contextsetup函數(shù)的第二個(gè)參數(shù),context是一個(gè)對(duì)象,里面包含了三個(gè)屬性,分別是

  • attrs

attrsVue2.0this.$attrs是一樣的,即外部傳入的未在props中定義的屬性。對(duì)于attrsprops一樣,我們不能對(duì)attrs使用es6的解構(gòu),必須使用attrs.name的寫(xiě)法

  • slots

slots對(duì)應(yīng)的是組件的插槽,與Vue2.0this.$slots是對(duì)應(yīng)的,與propsattrs一樣,slots也是不能解構(gòu)的。

  • emit

emit對(duì)應(yīng)的是Vue2.0this.$emit, 即對(duì)外暴露事件。

setup 返回值

setup函數(shù)一般會(huì)返回一個(gè)對(duì)象,這個(gè)對(duì)象里面包含了組件模板里面要使用到的data與一些函數(shù)或者事件,但是setup也可以返回一個(gè)函數(shù),這個(gè)函數(shù)對(duì)應(yīng)的就是Vue2.0render函數(shù),可以在這個(gè)函數(shù)里面使用JSX,對(duì)于Vue3.0中使用JSX,小編將在后面的系列文章中為您帶來(lái)更多說(shuō)明。

最后需要注意的是,不要在setup中使用this,在setup中的this和你真正要用到的this是不同的,通過(guò)propscontext基本是可以滿足我們的開(kāi)發(fā)需求的。

了解Composition API,先從reactiveref開(kāi)始

在使用Vue2.0的時(shí)候,我們一般聲明組件的屬性都會(huì)像下面的代碼一樣

export  default {
  data() {
    return {
      name: '編程獅',
      sex: '男'
    }
  }
}

然后就可以在需要用到的地方比如computed,watch,methods,template等地方使用,但是這樣存在一個(gè)比較明顯的問(wèn)題,即我聲明data的地方與使用data的地方在代碼結(jié)構(gòu)中可能相距很遠(yuǎn),有一種君住長(zhǎng)江頭,我住長(zhǎng)江尾,日日思君不見(jiàn)君,共飲一江水的感覺(jué)。而Composition API的誕生的一個(gè)很重要的原因就是解決這個(gè)問(wèn)題。在尤大大在關(guān)于Composition API的動(dòng)機(jī)中是這樣描述解決的問(wèn)題的:

  1. 隨著功能的增長(zhǎng),復(fù)雜組件的代碼變得越來(lái)越難以閱讀和理解。這種情況在開(kāi)發(fā)人員閱讀他人編寫(xiě)的代碼時(shí)尤為常見(jiàn)。根本原因是 Vue 現(xiàn)有的 API 迫使我們通過(guò)選項(xiàng)組織代碼,但是有的時(shí)候通過(guò)邏輯關(guān)系組織代碼更有意義。
  2. 目前缺少一種簡(jiǎn)潔且低成本的機(jī)制來(lái)提取和重用多個(gè)組件之間的邏輯。

現(xiàn)在我們先了解一下Compositon API中的reactiveref

介紹reactive

Vue2.6中, 出現(xiàn)了一個(gè)新的api,Vue.observer,通過(guò)這個(gè)api可以創(chuàng)建一個(gè)響應(yīng)式的對(duì)象,而reactive就和Vue.ovserver的功能基本是一致的。首先我們先來(lái)看一個(gè)例子

<template>
  <!--在模板中通過(guò)state.name使用setup中返回的數(shù)據(jù)-->
  <div>{{ state.name }}</div>
</template>
<script>
import { reactive } from "vue";
export default {
  setup() {
    // 通過(guò)reactive聲明一個(gè)可響應(yīng)式的對(duì)象
    const state = reactive({
      name: "編程獅"
    });
    // 5秒后將編程獅修改為 W3Cschool
    setTimeout(() => {
      state.name = "W3Cschool";
    }, 1000 * 5);
    // 將state添加到一個(gè)對(duì)象中然后返回
    return {
      state
    };
  }
};
</script>

上面的例子就是reactive的一個(gè)基本的用法,我們通過(guò)上面的代碼可以看到reactiveVue.observer聲明可響應(yīng)式對(duì)象的方法是很像的,但是他們之間還是存在一些差別的。我們?cè)谑褂?code>vue2.0的時(shí)候,最常見(jiàn)的一個(gè)問(wèn)題就是經(jīng)常會(huì)遇到一些數(shù)據(jù)明明修改了值,但是界面卻并沒(méi)有刷新,這時(shí)候就需要使用Vue.set來(lái)解決,這個(gè)問(wèn)題是因?yàn)?code>Vue2.0使用的Object.defineProperty無(wú)法監(jiān)聽(tīng)到某些場(chǎng)景比如新增屬性,但是到了Vue3.0中通過(guò)Proxy將這個(gè)問(wèn)題解決了,所以我們可以直接在reactive聲明的對(duì)象上面添加新的屬性,一起看看下面的例子

<template>
  <div>
    <div>姓名:{{ state.name }}</div>
    <div>網(wǎng)站:{{ state.wz }}</div>
  </div>
</template>
<script>
import { reactive } from "vue";
export default {
  setup() {
    const state = reactive({
      name: "編程獅"
    });
    // 5秒后新增屬性wz W3Cschool.cn
    setTimeout(() => {
      state.wz = "W3Cschool.cn";
    }, 1000 * 5);
    return {
      state
    };
  }
};
</script>

上面的例子雖然在state中并沒(méi)有聲明gzh屬性,但是在5s后我們可以直接給state添加gzh屬性,這時(shí)候并不需要使用Vue.set來(lái)解決新增屬性無(wú)法響應(yīng)的問(wèn)題。

在上面的代碼中,reactive通過(guò)傳入一個(gè)對(duì)象然后返回了一個(gè)state,需要注意的是state與傳入的對(duì)象是不用的,reactive對(duì)原始的對(duì)象并沒(méi)有進(jìn)行修改,而是返回了一個(gè)全新的對(duì)象,返回的對(duì)象是Proxy的實(shí)例。需要注意的是在項(xiàng)目中盡量去使用reactive返回的響應(yīng)式對(duì)象,而不是原始對(duì)象。

const obj = {}
const state = reactive(obj)
// 輸出false
console.log(obj === state)

介紹ref

假如現(xiàn)在我們需要在一個(gè)函數(shù)里面聲明用戶的信息,那么我們可能會(huì)有兩種不一樣的寫(xiě)法

// 寫(xiě)法1
let name = '編程獅'
let wz = 'W3Cschool.cn'
// 寫(xiě)法2
let userInfo = {
  name: '編程獅',
  wz: 'W3Cschool.cn'
}

上面兩種不同的聲明方式,我們使用的時(shí)候也是不同的,對(duì)于寫(xiě)法1我們直接使用變量就可以了,而對(duì)于寫(xiě)法2,我們需要寫(xiě)成userInfo.name的方式。我們可以發(fā)現(xiàn)userInfo的寫(xiě)法與reactive是比較相似的,而Vue3.0也提供了另一種寫(xiě)法,就像寫(xiě)法1一樣,即ref。先來(lái)看一個(gè)例子。

<template>
  <div>
    <div>姓名:{{ name }}</div>
  </div>
</template>
<script>
import { ref } from "vue";
export default {
  setup() {
    const name = ref("編程獅");
    console.log('姓名',name.value)
    // 5秒后修改name為 W3Cschool
    setTimeout(() => {
      name.value = "W3Cschool";
    }, 1000 * 5);
    return {
      name
    };
  }
};
</script>

通過(guò)上面的代碼,可以對(duì)比出來(lái)reactiveref的區(qū)別

  1. reactive傳入的是一個(gè)對(duì)象,返回的是一個(gè)響應(yīng)式對(duì)象,而ref傳入的是一個(gè)基本數(shù)據(jù)類型(其實(shí)引用類型也可以),返回的是傳入值的響應(yīng)式值
  2. reactive獲取或修改屬性可以直接通過(guò)state.prop來(lái)操作,而ref返回值需要通過(guò)name.value的方式來(lái)修改或者讀取數(shù)據(jù)。但是需要注意的是,在template中并不需要通過(guò).value來(lái)獲取值,這是因?yàn)?code>template中已經(jīng)做了解套。

Vue3.0優(yōu)雅的使用v-model

v-model并不是vue3.0新推出的新特性,在Vue2.0中我們已經(jīng)大量的到了v-model,但是V3V2還是有很大的區(qū)別的。本節(jié)我們將主要為大家?guī)?lái)如何在Vue3.0中使用v-model,Vue3.0中的v-model提供了哪些驚喜以及如何在Vue3.0中自定義v-model。

Vue2.0Vue3.0中使用v-model

Vue2.0中如何實(shí)現(xiàn)雙向數(shù)據(jù)綁定呢?常用的方式又兩種,一種是v-model,另一種是.sync,為什么會(huì)有兩種呢?這是因?yàn)橐粋€(gè)組件只能用于一個(gè)v-model,但是有的組件需要有多個(gè)可以雙向響應(yīng)的數(shù)據(jù),所以就出現(xiàn)了.sync。在Vue3.0中為了實(shí)現(xiàn)統(tǒng)一,實(shí)現(xiàn)了讓一個(gè)組件可以擁有多個(gè)v-model,同時(shí)刪除掉了.sync。如下面的代碼,分別是Vue2.0Vue3.0使用v-model的區(qū)別。

  1. Vue2.0中使用v-model

   <template>
     <a-input v-model="value" placeholder="Basic usage" />
   </template>
   <script>
   export default {
     data() {
       return {
         value: '',
       };
     },
   };
   </script>

  1. Vue3.0中使用v-model

   <template>
     <!--在vue3.0中,v-model后面需要跟一個(gè)modelValue,即要雙向綁定的屬性名-->
     <a-input v-model:value="value" placeholder="Basic usage" />
   </template>
   <script>
   export default {
     // 在Vue3.0中也可以繼續(xù)使用`Vue2.0`的寫(xiě)法
     data() {
       return {
         value: '',
       };
     },
   };
   </script>

vue3.0中,v-model后面需要跟一個(gè)modelValue,即要雙向綁定的屬性名,Vue3.0就是通過(guò)給不同的v-model指定不同的modelValue來(lái)實(shí)現(xiàn)多個(gè)v-model。對(duì)于v-model的原理,下文將通過(guò)自定義v-model來(lái)說(shuō)明。

自定義v-model

使用Vue2.0自定義一個(gè)v-model示例

  1. 組件代碼

<template>
  <div class="custom-input">
    <input :value="value" @input="$_handleChange" />
  </div>
</template>
<script>
export default {
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  methods: {
    $_handleChange(e) {
      this.$emit('input', e.target.value)
    }
  }
}
</script>

2 . 在代碼中使用組件

<template>
      <custom-input v-model="value"></custom-input>
</template>
<script>
 export default {
    data() {
      return {
        value: ''
      }
    }
  }
</script>

Vue2.0中我們通過(guò)為組件設(shè)置名為value屬性同時(shí)觸發(fā)名為input的事件來(lái)實(shí)現(xiàn)的v-model,當(dāng)然也可以通過(guò)model來(lái)修改屬性名和事件名,可以看我以前的文章中有詳解。

使用Vue3.0自定義一個(gè)v-model示例

  1. 組件代碼

   <template>
     <div class="custom-input">
       <input :value="value" @input="_handleChangeValue" />
     </div>
   </template>
   <script>
   export default {
     props: {
       value: {
         type: String,
         default: ""
       }
     },
     name: "CustomInput",
     setup(props, { emit }) {
       function _handleChangeValue(e) {
         // vue3.0 是通過(guò)emit事件名為 update:modelValue來(lái)更新v-model的
         emit("update:value", e.target.value);
       }
       return {
         _handleChangeValue
       };
     }
   };
   </script>

到了Vue3.0中,因?yàn)橐粋€(gè)組件支持多個(gè)v-model,所以v-model的實(shí)現(xiàn)方式有了新的改變。首先我們不需要使用固定的屬性名和事件名了,在上例中因?yàn)槭?code>input輸入框,屬性名我們依然使用的是value,但是也可以是其他任何的比如name,data,val等等,而在值發(fā)生變化后對(duì)外暴露的事件名變成了update:value,即update:屬性名。而在調(diào)用組件的地方也就使用了v-model:屬性名來(lái)區(qū)分不同的v-model。

  1. 在代碼中使用組件

<template>
  <!--在使用v-model需要指定modelValue-->
  <custom-input v-model:value="state.inputValue"></custom-input>
</template>
<script>
import { reactive } from "vue";
import CustomInput from "../components/custom-input";
export default {
  name: "Home",
  components: {
    CustomInput
  },
  setup() {
    const state = reactive({
      inputValue: ""
    });
    return {
      state
    };
  }
};
</script>

總結(jié)

在本文中我們主要講解了開(kāi)發(fā)環(huán)境的搭建,setup,reactive,ref,v-model等的介紹,同時(shí)通過(guò)對(duì)比Vue3.0Vue2.0的不同,讓大家對(duì)Vue3.0有了一定的了解。

以上就是W3Cschool編程獅關(guān)于使用Vue3.0,我收獲了哪些知識(shí)點(diǎn)(一)的相關(guān)介紹了,希望對(duì)大家有所幫助。

0 人點(diǎn)贊