這篇文章主要是將自己前期學(xué)習(xí)Vue3.0
時(shí)候整理的一些筆記內(nèi)容進(jìn)行了匯總,通過對本文的閱讀,你將可以自己完成Vue3.0
環(huán)境搭建,同時(shí)還會對Vue3.0
的一些新的特性進(jìn)行了解,方便自己進(jìn)行Vue3.0
的學(xué)習(xí)。
本文所有的示例均使用
ant design vue2.0
實(shí)現(xiàn),關(guān)于ant design vue2.0
請參考 2x.antdv.com/docs/vue/introduce-cn/
初始化環(huán)境
在前面的文章中,我們通過vite
搭建了一個(gè)開發(fā)環(huán)境,但是實(shí)際上現(xiàn)在vite
并沒有完善到支撐一個(gè)完整項(xiàng)目的地步,所以本文我們依然選擇使用vue-cli
腳手架進(jìn)行環(huán)境搭建。
小編使用的
vue-cli
版本是4.5.4
,如果您的版本比較舊可以通過npm update @vue/cli
來升級腳手架版本,如果沒有安裝可以通過npm install @vue/cli -g
進(jìn)行安裝
使用腳手架新建項(xiàng)目
- 在工作空間打開終端(
cmd
),然后通過vue create my-vue3-test
命令初始化項(xiàng)目
- 在第一步先選擇
Manually select features
,進(jìn)行手動(dòng)選擇功能
- 然后通過
Space
和上下鍵依次選擇
Choose Vue version
Babel
TypeScript
Router
Vuex
CSS Pre-processors
Linter/Formatter
4.然后回車
- 然后提示選擇
Vue
版本,選擇3.x(Preview)
Use class-style component syntax?
選擇n
,即輸入n
然后回車- 然后提示
Use Babel alongside TypeScript,輸入
y` Use history mode for router
輸入n
- 然后
css
預(yù)處理器選擇Less
eslint
選擇ESLint + Prettier
- 然后是
Lint on save
和In dedicater config files
- 最后一路回車即可完成項(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)之后即可通過訪問http://localhost:8080/
訪問項(xiàng)目
配置ant design vue
在當(dāng)前Vue3.0
正式版還未發(fā)布之際,國內(nèi)比較出名的前端UI
庫中率先將Vue3.0
繼承到自家的UI
庫中的,PC
端主要是ant-design-vue
,移動(dòng)端主要是vant
, 本文所有示例代碼都會基于ant-design-vue
來進(jìn)行,首先我們先安裝ant-design-vue
- 安裝依賴
yarn add ant-design-vue@2.0.0-beta.6
yarn add babel-plugin-import -D
- 配置
ant-design-vue
按需加載
進(jìn)入項(xiàng)目根目錄,然后打開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" }
]
]
};
- 嘗試使用
vue3 + antdv
來添加一個(gè)小頁面, 我們直接將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
對于Vue3.0
的問世,最吸引大家注意力的便是Vue3.0
的Composition API
,對于Componsition API
,可以說是兩極分化特別嚴(yán)重,一部分人特別喜歡這個(gè)新的設(shè)計(jì)與開發(fā)方式,而另一部分人則感覺使用Composition API
很容易寫出來意大利面式的代碼(可能這部分人不知道蘭州拉面吧)。到底Composition API
是好是壞,小編不做評論,反正我只是一個(gè)搬磚的。而本小節(jié)介紹的setup
就是Composition API
的入口。
setup介紹
setup
是Vue3.0
提供的一個(gè)新的屬性,可以在setup
中使用Composition API
,在上面的示例代碼中我們已經(jīng)使用到了setup
,在上文代碼中我們在setup
中通過reactive
初始化了一個(gè)響應(yīng)式數(shù)據(jù),然后通過return
返回了一個(gè)對象,對象中包含了聲明的響應(yīng)式數(shù)據(jù)和一個(gè)方法,而這些數(shù)據(jù)就可以直接使用到了template
中了,就像上文代碼中的那樣。關(guān)于reactive
,我將會在下一小節(jié)為你帶來說明。
setup 的參數(shù)說明
setup
函數(shù)有兩個(gè)參數(shù),分別是props
和context
。
props
props
是setup
函數(shù)的第一個(gè)參數(shù),是組件外部傳入進(jìn)來的屬性,與vue2.0
的props
基本是一致的,比如下面代碼
export default {
props: {
value: {
type: String,
default: ""
}
},
setup(props) {
console.log(props.value)
}
}
但是需要注意的是,在setup
中,props
是不能使用解構(gòu)的,即不能將上面的代碼改寫成
setup({value}) {
console.log(value)
}
雖然template
中使用的是setup
返回的對象,但是對于props
,我們不需要在setup
中返回,而是直接可以在template
使用,比如上面的value
,可以直接在template
寫成
<custom-component :value="value"></custom-component>
context
context
是setup
函數(shù)的第二個(gè)參數(shù),context
是一個(gè)對象,里面包含了三個(gè)屬性,分別是
attrs
attrs
與Vue2.0
的this.$attrs
是一樣的,即外部傳入的未在props
中定義的屬性。對于attrs
與props
一樣,我們不能對attrs
使用es6
的解構(gòu),必須使用attrs.name
的寫法
slots
slots
對應(yīng)的是組件的插槽,與Vue2.0
的this.$slots
是對應(yīng)的,與props
和attrs
一樣,slots
也是不能解構(gòu)的。
emit
emit
對應(yīng)的是Vue2.0
的this.$emit
, 即對外暴露事件。
setup 返回值
setup
函數(shù)一般會返回一個(gè)對象,這個(gè)對象里面包含了組件模板里面要使用到的data
與一些函數(shù)或者事件,但是setup
也可以返回一個(gè)函數(shù),這個(gè)函數(shù)對應(yīng)的就是Vue2.0
的render
函數(shù),可以在這個(gè)函數(shù)里面使用JSX
,對于Vue3.0
中使用JSX
,小編將在后面的系列文章中為您帶來更多說明。
最后需要注意的是,不要在
setup
中使用this
,在setup
中的this
和你真正要用到的this
是不同的,通過props
和context
基本是可以滿足我們的開發(fā)需求的。
了解Composition API
,先從reactive
和ref
開始
在使用Vue2.0
的時(shí)候,我們一般聲明組件的屬性都會像下面的代碼一樣
export default {
data() {
return {
name: '編程獅',
sex: '男'
}
}
}
然后就可以在需要用到的地方比如computed
,watch
,methods
,template
等地方使用,但是這樣存在一個(gè)比較明顯的問題,即我聲明data
的地方與使用data
的地方在代碼結(jié)構(gòu)中可能相距很遠(yuǎn),有一種君住長江頭,我住長江尾,日日思君不見君,共飲一江水
的感覺。而Composition API
的誕生的一個(gè)很重要的原因就是解決這個(gè)問題。在尤大大在關(guān)于Composition API
的動(dòng)機(jī)中是這樣描述解決的問題的:
- 隨著功能的增長,復(fù)雜組件的代碼變得越來越難以閱讀和理解。這種情況在開發(fā)人員閱讀他人編寫的代碼時(shí)尤為常見。根本原因是 Vue 現(xiàn)有的 API 迫使我們通過選項(xiàng)組織代碼,但是有的時(shí)候通過邏輯關(guān)系組織代碼更有意義。
- 目前缺少一種簡潔且低成本的機(jī)制來提取和重用多個(gè)組件之間的邏輯。
現(xiàn)在我們先了解一下Compositon API
中的reactive
和ref
介紹reactive
在Vue2.6
中, 出現(xiàn)了一個(gè)新的api
,Vue.observer
,通過這個(gè)api
可以創(chuàng)建一個(gè)響應(yīng)式的對象,而reactive
就和Vue.ovserver
的功能基本是一致的。首先我們先來看一個(gè)例子
<template>
<!--在模板中通過state.name使用setup中返回的數(shù)據(jù)-->
<div>{{ state.name }}</div>
</template>
<script>
import { reactive } from "vue";
export default {
setup() {
// 通過reactive聲明一個(gè)可響應(yīng)式的對象
const state = reactive({
name: "編程獅"
});
// 5秒后將編程獅修改為 W3Cschool
setTimeout(() => {
state.name = "W3Cschool";
}, 1000 * 5);
// 將state添加到一個(gè)對象中然后返回
return {
state
};
}
};
</script>
上面的例子就是reactive
的一個(gè)基本的用法,我們通過上面的代碼可以看到reactive
和Vue.observer
聲明可響應(yīng)式對象的方法是很像的,但是他們之間還是存在一些差別的。我們在使用vue2.0
的時(shí)候,最常見的一個(gè)問題就是經(jīng)常會遇到一些數(shù)據(jù)明明修改了值,但是界面卻并沒有刷新,這時(shí)候就需要使用Vue.set
來解決,這個(gè)問題是因?yàn)?code>Vue2.0使用的Object.defineProperty
無法監(jiān)聽到某些場景比如新增屬性,但是到了Vue3.0
中通過Proxy
將這個(gè)問題解決了,所以我們可以直接在reactive
聲明的對象上面添加新的屬性,一起看看下面的例子
<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
中并沒有聲明gzh
屬性,但是在5s
后我們可以直接給state
添加gzh
屬性,這時(shí)候并不需要使用Vue.set
來解決新增屬性無法響應(yīng)的問題。
在上面的代碼中,reactive
通過傳入一個(gè)對象然后返回了一個(gè)state
,需要注意的是state
與傳入的對象是不用的,reactive
對原始的對象并沒有進(jìn)行修改,而是返回了一個(gè)全新的對象,返回的對象是Proxy
的實(shí)例。需要注意的是在項(xiàng)目中盡量去使用reactive
返回的響應(yīng)式對象,而不是原始對象。
const obj = {}
const state = reactive(obj)
// 輸出false
console.log(obj === state)
介紹ref
假如現(xiàn)在我們需要在一個(gè)函數(shù)里面聲明用戶的信息,那么我們可能會有兩種不一樣的寫法
// 寫法1
let name = '編程獅'
let wz = 'W3Cschool.cn'
// 寫法2
let userInfo = {
name: '編程獅',
wz: 'W3Cschool.cn'
}
上面兩種不同的聲明方式,我們使用的時(shí)候也是不同的,對于寫法1
我們直接使用變量就可以了,而對于寫法2
,我們需要寫成userInfo.name
的方式。我們可以發(fā)現(xiàn)userInfo
的寫法與reactive
是比較相似的,而Vue3.0
也提供了另一種寫法,就像寫法1
一樣,即ref
。先來看一個(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>
通過上面的代碼,可以對比出來reactive
與ref
的區(qū)別
reactive
傳入的是一個(gè)對象,返回的是一個(gè)響應(yīng)式對象,而ref
傳入的是一個(gè)基本數(shù)據(jù)類型(其實(shí)引用類型也可以),返回的是傳入值的響應(yīng)式值reactive
獲取或修改屬性可以直接通過state.prop
來操作,而ref
返回值需要通過name.value
的方式來修改或者讀取數(shù)據(jù)。但是需要注意的是,在template
中并不需要通過.value
來獲取值,這是因?yàn)?code>template中已經(jīng)做了解套。
在Vue3.0
優(yōu)雅的使用v-model
v-model
并不是vue3.0
新推出的新特性,在Vue2.0
中我們已經(jīng)大量的到了v-model
,但是V3
和V2
還是有很大的區(qū)別的。本節(jié)我們將主要為大家?guī)砣绾卧?code>Vue3.0中使用v-model
,Vue3.0
中的v-model
提供了哪些驚喜以及如何在Vue3.0
中自定義v-model
。
在Vue2.0
和Vue3.0
中使用v-model
在Vue2.0
中如何實(shí)現(xiàn)雙向數(shù)據(jù)綁定呢?常用的方式又兩種,一種是v-model
,另一種是.sync
,為什么會有兩種呢?這是因?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.0
與Vue3.0
使用v-model
的區(qū)別。
- 在
Vue2.0
中使用v-model
<template>
<a-input v-model="value" placeholder="Basic usage" />
</template>
<script>
export default {
data() {
return {
value: '',
};
},
};
</script>
- 在
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`的寫法
data() {
return {
value: '',
};
},
};
</script>
在vue3.0
中,v-model
后面需要跟一個(gè)modelValue
,即要雙向綁定的屬性名,Vue3.0
就是通過給不同的v-model
指定不同的modelValue
來實(shí)現(xiàn)多個(gè)v-model
。對于v-model
的原理,下文將通過自定義v-model
來說明。
自定義v-model
使用Vue2.0
自定義一個(gè)v-model
示例
- 組件代碼
<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
中我們通過為組件設(shè)置名為value
屬性同時(shí)觸發(fā)名為input
的事件來實(shí)現(xiàn)的v-model
,當(dāng)然也可以通過model
來修改屬性名和事件名,可以看我以前的文章中有詳解。
使用Vue3.0
自定義一個(gè)v-model
示例
- 組件代碼
<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 是通過emit事件名為 update:modelValue來更新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ā)生變化后對外暴露的事件名變成了update:value
,即update:屬性名
。而在調(diào)用組件的地方也就使用了v-model:屬性名
來區(qū)分不同的v-model
。
- 在代碼中使用組件
<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é)
在本文中我們主要講解了開發(fā)環(huán)境的搭建,setup
,reactive
,ref
,v-model
等的介紹,同時(shí)通過對比Vue3.0
與Vue2.0
的不同,讓大家對Vue3.0
有了一定的了解。
以上就是W3Cschool編程獅
關(guān)于使用Vue3.0,我收獲了哪些知識點(diǎn)(一)的相關(guān)介紹了,希望對大家有所幫助。