1. 項目初始化
1.1 安裝 vue-cli
- 第一步安裝
vue-cli:注意! 如果在vue2中已經(jīng)安裝過這里就不需要再安裝了。
npm install -g @vue/cli
- 以下安裝方式是錯誤的:
npm install -g vue
npm install -g vue-cli
- 安裝成功后,我們即可使用
vue命令,測試方法:
vue -V
1.2 初始化 vue 項目
- 使用
vue2.0中創(chuàng)建項目的方式創(chuàng)建項目 :
vue create project-name
- 輸入命令后,會出現(xiàn)命令行交互窗口,這里我們選擇
Manually select features(手動選擇) :
Vue CLI v4.3.1
? Please pick a preset:
default (babel, eslint)
? Manually select features
- 隨后我們勾選:
Router、Vuex、CSS Pre-processors和Linter / Formatter,這些都是開發(fā)商業(yè)級項目必須的:
Vue CLI v4.3.1
? Please pick a preset: Manually select features
? Check the features needed for your project:
? Babel
? TypeScript
? Progressive Web App (PWA) Support
? Router
? Vuex
? CSS Pre-processors
?? Linter / Formatter
? Unit Testing
? E2E Testing
注意:在初始化項目的時候需要對
Router、Vuex進行同時安裝。因為此時項目還屬于使用vue 2.0創(chuàng)建,如果后期升級vue3.0時可以同時升級Router和Vuex的版本。
小提示: 回車后會自動安裝依賴,為了加速安裝速度,我們可以使用淘寶源來加快初始化速度 。
vue create -r https://registry.npm.taobao.org project-name
2. 升級為 Vue 3.0 項目
- 目前創(chuàng)建
Vue 3.0項目需要通過插件升級的方式來實現(xiàn),vue-cli還沒有直接支持,我們進入項目目錄,并輸入以下指令:
cd project-name // 切換到項目目錄下
vue add vue-next
- 執(zhí)行上述指令后,會自動安裝 vue-cli-plugin-vue-next 插件(查看vue3.0項目代碼),該插件會完成以下操作:
- 安裝
Vue 3.0依賴;- 更新
Vue 3.0 webpack loader配置,使其能夠支持.vue文件構(gòu)建(這點非常重要);- 創(chuàng)建
Vue 3.0的模板代碼;- 自動將代碼中的
Vue Router和Vuex升級到4.0版本,如果未安裝則不會升級;- 自動生成
Vue Router和Vuex模板代碼。
完成上述操作后,項目正式升級到
Vue 3.0,注意該插件還不能支持typescript。在升級為
Vue 3.0版本之后啟動項目報如下錯誤 :
ERROR Error: Cannot find module 'vue-loader-v16/package.json'
2.1 解決升級 vue 3.0 之后 vue-loader-v16找不到問題
查詢資料找到一篇文章中的解決方案: vue3項目報錯 Error: Cannot find module ‘vue-loader-v16/package.json‘
升級
npm
npm i -g npm
- 刪除并重新安裝
node_modules依賴包
npm i
- 重新下載
vue-loader-v16
cnpm i -D vue-loader-v16
3. Vue 3.0 基本特性的體驗
3.1 創(chuàng)建頁面并添加新的路由
- 項目開發(fā)中,我們通常需要創(chuàng)建新頁面,然后添加路由配置,我們在
/src/views目錄下創(chuàng)建Test.vue:
<template>
<div class="test">
<h1>test page</h1>
</div>
</template>
<script>
export default {
}
</script>
<style lang="less" scoped>
.test {
color: red;
}
</style>
- 之后在
/src/router/index.js中創(chuàng)建路由配置:
import {createRouter, createWebHashHistory} from 'vue-router';
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/test',
name: 'Test',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/Test.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
- 初始化
Vue Router的過程與3.0版本變化不大,只是之前采用構(gòu)造函數(shù)的方式,這里改為使用createRouter來創(chuàng)建Vue Router實例,配置的方法基本一致,配置完成后我們還需要在App.vue中增加鏈接到Test.vue的路由:
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/test">Test</router-link>
</div>
<router-view/>
</div>
</template>
3.2 CompositionApi(一)

vue3.0中CompositionAPI的具體體現(xiàn)
/* CompositionAPI */
import {reactive, watchEffect} from 'vue'
/**
* 創(chuàng)建狀態(tài)
* @type {UnwrapNestedRefs<{count: number}>}
*/
const state = reactive({
count: 1
})
/**
* 進行累加操作
* */
const increment = () => {
state.count++
}
/**
* 觀察效果
*/
watchEffect(() => {
document.body.innerHTML = `count:${state.count}`
document.body.addEventListener('click', increment)
})
3.3 Vue3.0中狀態(tài)和事件綁定 、計算屬性和監(jiān)聽器
-
Vue 3.0中定義狀態(tài)的方法改為類似React Hooks的方法,下面我們在CompositionApiContinue.vue中定義一個狀態(tài)count: 從vue中導入ref對狀態(tài)進行初始化
// 初始化 count 的值為 1
const count = ref(1)
-
Vue 3.0中初始化狀態(tài)通過setup方法,定義狀態(tài)需要調(diào)用ref方法。接下來我們定義一個事件,用來更新count狀態(tài):注意這里對count的修改需要修改count的value屬性。
const add = () => {
// 對狀態(tài)的值進行改變 需要使用 value
count.value++
}
- 這些定義好的狀態(tài)和事件需要通過
return返回一個對象進行返回:
// 初始化完成之后需要進行返回
return {
count,
add,
doubleCount,
threeCount
}
- 使用
watch監(jiān)聽狀態(tài)的改變: 需要在vue中導入watch函數(shù)
// 使用 watch 監(jiān)聽值的改變
/**
* 注意watch 傳遞的第一個參數(shù)需要是函數(shù)的返回值
*/
watch(() => count.value, (newVal, oldVal) => {
console.log(newVal)
console.log(oldVal)
})
- 使用
Vue3.0中的計算屬性,需要在Vue中導入computed函數(shù):
// 計算屬性
const doubleCount = computed(() => count.value * 2)
const threeCount = computed(() => count.value * 3)
- 完整代碼:
<template>
<!-- vue 3.0 中狀態(tài)和事件綁定 -->
<div class="composition-api">
<h1>test count : {{count}}</h1>
<h1>test doubleCount : {{doubleCount}}</h1>
<h1>test threeCount : {{threeCount}}</h1>
<button @click="add">add</button>
</div>
</template>
<script>
/* 狀態(tài)初始化 、 事件綁定 、 計算屬性 、 監(jiān)聽器 */
import {ref, computed, watch} from 'vue'
export default {
name: "index",
// 在 vue 3.0 中初始化狀態(tài)使用 setup
setup() {
// 初始化 count 的值為 1
const count = ref(1)
const add = () => {
// 對狀態(tài)的值進行改變 需要使用 value
count.value++
}
// 使用 watch 監(jiān)聽值的改變
/**
* 注意watch 傳遞的第一個參數(shù)需要是函數(shù)的返回值
*/
watch(() => count.value, (newVal, oldVal) => {
console.log(newVal)
console.log(oldVal)
})
// 計算屬性
const doubleCount = computed(() => count.value * 2)
const threeCount = computed(() => count.value * 3)
// 初始化完成之后需要進行返回
return {
count,
add,
doubleCount,
threeCount
}
}
}
</script>
3.4 Vue 3.0 中 Vue-Router的使用
- 首先要獲取
$router(全局)和$route(局部)這兩個對象首先需要獲取到當前的Vue實例。此時需要從vue中導入一個getCurrentInstance的方法用于獲取vue實例。
/* 在vue 中導入 獲取當前 Vue 實例的方法 */
import {getCurrentInstance} from 'vue'
export default {
name: "index",
// 設置數(shù)據(jù)的方法
setup() {
const {ctx} = getCurrentInstance()
// 獲取全局的路由對象
console.log(ctx.$router)
/**
* 跳轉(zhuǎn)到 about 頁面
*/
const goToAbout = () => {
ctx.$router.push('/about')
}
// 獲取當前路由對象
console.log(ctx.$route)
return {
goToAbout
}
}
}
3.5 Vue 3.0 中 Vuex 的使用
-
vuex中的代碼:
import Vuex from 'vuex'
export default Vuex.createStore({
state: {
number: 100
},
mutations: {
SET_NUMBER(state, value) {
state.number = value
}
},
actions: {
setNumber({commit}, value) {
commit('SET_NUMBER', value)
}
},
modules: {
a: {
state: {
aa: 10
},
mutations: {
SET_AA(state, value) {
state.aa = value
}
},
getters: {
aaValue: (state) => state.aa
}
},
b: {
state: {
bb: 22
},
/**
* 同步方法
*/
mutations: {
SET_BB(state, value) {
state.bb = value
}
},
/**
* 異步方法
*/
actions: {}
}
}
});
- 頁面中的代碼 :
import {getCurrentInstance, ref, computed} from 'vue'
export default {
name: "index",
setup() {
const count = ref(1)
// 獲取當前的 vue 實例
const {ctx} = getCurrentInstance()
// 獲取 vuex 中的 state 中的值 這兒需要使用計算屬性獲取在后面才能改變其值
const number = computed(() => ctx.$store.state.number)
// 通過 mutations 修改 vuex 中的 number 值
const updateNumber = () => {
count.value++
// ctx.$store.commit('SET_NUMBER', ctx.$store.state.number * 2)
// 調(diào)用actions中的異步方法
ctx.$store.dispatch('setNumber', ctx.$store.state.number * 3)
}
const aa = computed(() => ctx.$store.getters.aaValue)
// 更新aa的值
const updateAA = () => {
ctx.$store.commit('SET_AA', ctx.$store.state.a.aa * 5)
}
return {
number,
updateNumber,
aa,
updateAA
}
}
}