2020註定是不平凡的一年,不管是疫情的橫空出世,仍是世界局勢的激烈動盪,抑或是股市的跌宕起伏,我相信不少國人都會有一種慶幸我是中國人的深入感悟。做爲一名技術宅,除了疫情,更多的仍是雨女無瓜,隨着Vue3.0 Beta
的推出,你們都爭先恐後的嚐了鮮,筆者也不例外,通過一番研究,以爲Vue3
也的確存在它獨特的魅力,也應該寫一篇博客方便尚未體驗的朋友可以快速對其有一個大致的認知。javascript
此文默認你已熟悉
Vue2.x
相關知識vue
相關庫版本java
Vue-Cli 4.x
Vue 3.0.0-beta.1
Vue-Router 4.0.0-alpha.7
具體步驟以下:react
VueCli
建立一個Vue
基礎項目:vue create project
vue add vue-next
項目目錄結構以下:vue-router
進行完以上操做無誤以後基本環境就已經搭建完畢。npm
npm install vue-router@4.0.0-alpha.7 -S
按照通常規範,在src
目錄下新建router
文件夾,並在router
文件夾中新建index.js
文件。api
index.js內容:app
import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '../components/home'
const routes = [
{path: '/', redirect: '/home'},
{path: '/home', component: Home}
]
export default createRouter({
history: createWebHashHistory(),
routes
})
複製代碼
基本的路由配置沒有太大改變,大多數狀況下你只須要關注routes
中路由規則編寫。接下來,咱們須要在main.js
中接入router
。框架
main.js:dom
import { createApp } from 'vue';
import App from './App.vue'
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
複製代碼
不一樣於咱們以前採用new Vue()
建立實例的方式,Vue3
在這裏進行了改變;不只如此,咱們不難發現,安裝路由的方式也由以前的Vue.use(Router)
變成如上方式,同理對於Vuex
的接入也是大同小異,筆者這裏就不過多贅述了。
App.js
<template>
<div id="app"> <router-view></router-view> </div> </template>
複製代碼
setup功能是新的組件選項,它充當在組件內部使用Composition API(新特性)的入口點;建立組件實例時,在初始道具解析後當即調用。在生命週期方面,它在beforeCreate掛接以前被調用。
通常來講,按照咱們以前常規的寫法,咱們在對須要使用變量、計算屬性的時候,咱們會習慣性的寫上:
home/index.vue
<template>
<div class='home'>
<div>{{count}}</div>
<div>{{foo}}</div>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: 'home',
data() {
return {
count: 0
}
},
computed: {
foo() {
return this.count + 1;
}
}
};
複製代碼
二者是須要被分類到各自的對象中,在同等功能實現上來講,Vue3
的實現以下:
<template>
<div class='home'>
<div>{{count}}</div>
<div>{{foo}}</div>
</div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
name: 'home',
setup(props, context) {
const count = ref(0)
const foo = computed(() => count.value + 1)
return {
count,
foo
}
}
};
</script>
複製代碼
看到這種語法你是否是懵了,不用慌,這部分着重介紹
setup
這個入口函數,具體內部語法能夠先不用在乎,後面都會進行對應性一一講解。
setup
接收兩個重要參數:
vue2
的props
,在這個地方咱們須要注意的地方是,咱們不能對這個參數進行解構,若是使用解構會使他失去響應性。例以下面代碼就會讓props
傳過來的值失去響應性:export default {
props: {
name: String
},
setup({ name }) {
watchEffect(() => {
console.log(`name is: ` + name) // 失去響應性!
})
}
}
複製代碼
attrs
、slots
、emit
),舉個栗子:setup(props, context) {
context.attrs // 2.x:this.attrs
context.slots // 2.x:this.slots
context.emit // 2.x:this.emit
}
複製代碼
看完代碼,咱們基本能夠理解爲setup
函數就是咱們整個組件各項邏輯關係以及操做的入口了,在Vue3
中,咱們使用不一樣api
的方式都是採用導入的形式,這就至關於咱們有了更大的操做空間,有了更大的自由性。
雖說Vue3
向下兼容Vue2
,可是這裏其實咱們須要注意的是,咱們應該儘可能避免2.x和setup
函數的混用,這將會致使一些問題。
取得一個對象並返回原始對象的反應式代理。這等效於2.x的
Vue.observable()
。
對這個api
用法,筆者用代碼講解會比較好理解:
<template>
<div class='home'>
<div>{{name}}</div>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'home',
setup() {
const obj = reactive({name: '流星啊'})
obj.name = 'bilibili'; // 修改屬性值
return obj;
}
};
</script>
複製代碼
相信你們已經看出來端倪,沒錯,這個api
就是單純的把一個對象變得可響應。
接受一個內部值並返回一個反應性且可變的ref對象。ref對象具備.value指向內部值的單個屬性。
在這裏我估計有小夥伴就要問了,這不就是2.x裏的ref嗎,不不不,在3.x它跟那個種在標籤上的
ref
沒有半點關係,也和$refs
沒有任何關係,對於新的相似於2.x的獲取dom
的方式請看模板引用部分。
一樣,舉個栗子:
<template>
<div class='home'>
<div>{{count}}</div>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: 'home',
setup() {
const count = ref(0);
count.value++; // 有疑問的往下看筆者介紹
console.log(count.value);
return {
count
};
}
};
</script>
複製代碼
這裏也有一個注意點,你若是想要修改使用ref構造出來的變量,只能對xxx.value
進行修改,同理你想要在js
中訪問它的值必須使用xxx.value
,直接對count進行賦值如count++
,這種寫法會報錯。
在這裏估計又有小夥伴要問了,那爲啥在template
模板中使用{{count}}
訪問的時候不用加.value
,這裏其實你在使用插值表達式的時候,它內部會自動展開,因此咱們直接用就好了。
若是說咱們把reactive
和ref
結合起來用會有怎樣的奇淫巧計呢😱,繼續舉個栗子:
const count = ref(0)
const state = reactive({
count
})
console.log(state.count) // 0
state.count = 1
console.log(count.value) // 1
複製代碼
當ref被訪問或做爲反應對象的屬性進行更改時,它會自動展開爲內部值,所以其行爲相似於普通屬性。
這個api
也相似2.x,可使用getter
、setter
,話很少說,上代碼:
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 無效
複製代碼
在這裏咱們不難發現,它的訪問方式也等同於ref
,也是須要採用xxx.value
,與此同時呢,若是你想要修改一個計算屬性的值,你必須爲他設置setter
,並對相應的依賴進行修改。廢話少說,看碼:
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
複製代碼
意如其名,顧名思義,就是構造一個只能訪問的屬性,這個玩意它針對的很強,也就是不管你這個對象嵌套有多深,被他包裝後的對象必定是隻能讀,其實就是至關於一個代理:
const re = reactive({count: 0})
const readonlyRe = readonly(re);
readonlyRe.count++; // 無效,而且會給出警告
複製代碼
對於這個屬性呢,你能夠拿它跟2.x的watch
對象相比較了,沒錯他就是來監聽的。
const count = ref(0)
watchEffect(() => console.log(count.value))
// -> 打印 0
setTimeout(() => {
count.value++
// -> 打印 1
}, 100)
複製代碼
總而言之,他會收集傳入函數的依賴,一旦依賴發生發生改變,他就會從新調用你傳進來的函數,用過react hooks
的童靴可能會說,這玩意怎麼這麼像useEffect
,其實Vue3
也的確借鑑了react
一些不錯的設計,因此,你們也不要以爲抄襲不抄襲的,框架終究是爲用戶服務,好的設計天然應該值得借鑑,就像react
也有借鑑Vue
的一些優勢對自身進行優化。
接下來咱們繼續刨析這個api
。調用這個api
的同時,它會返回一個用於暫停句柄的函數,咱們能夠顯式調用它用於的中止當前監聽,而且對於傳入給watchEffect
的回調函數,這個api
在觸發調用的時候會傳入一個用於註冊無效回調的函數onInvalidate
。具體例子以下:
const stop = watchEffect(onInvalidate => {
const token = performAsyncOperation(id.value); // 執行一個異步操做
onInvalidate(() => {
// 依賴的id發生變化,可是異步操做還未完成,咱們就能夠在這裏中止你的異步操做。
token.cancel(); // 這裏咱們假設你的異步操做返回了一個包含取消操做的方法。
})
})
stop(); // 咱們可使用這個方法去中止它
複製代碼
若是咱們註冊了無效回調方法,那麼在這個依賴已經變化可是異步請求還未完成的時候,它內部就會幫咱們調用咱們註冊的無效回調。
這裏給一個與2.x的對比:
beforeCreate (vue3棄用) -> 使用 setup()
created (vue3棄用) -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured
使用示例:
import { onMounted, onUpdated, onUnmounted } from 'vue'
const MyComponent = {
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
}
}
複製代碼
在看完前面ref
這個api的介紹以後,很對小夥伴確定也會疑惑,那我要獲取dom
怎麼辦,這個Vue3
也有的,放寬心,聽筆者繼續娓娓道來。
<template>
<div class='home'>
<div ref="dom"></div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
name: 'home',
setup() {
const dom = ref(null)
onMounted(() => {
console.log(dom.value);
})
return {
dom
}
}
};
</script>
複製代碼
從代碼中咱們能夠發現,如今這種訪問dom
的方式和以前區別在於,咱們須要顯示設定一個響應性變量,而後再在模板中使用以前咱們耳熟能詳的方式ref='xxx'
來進行設定。
聽完筆者的敘述,你有沒有對Vue3
有一種躍躍欲試的想法呢😜。
若有發現筆者表述不當的地方,請在評論區戳筆者哦,感激涕零😝。