![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2UTN1kDO3gjNtcjNxYTN1IjMyUjMwEDMyAjMtkDN1kTN48CXwEDMyAjMvwVO0UTO1gzLcd2bsJ2Lc12bj5ycn9Gbi52YuAjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
學習一門新的技術,我認為最好的方式就是通過 Demo 去制造使用場景,通覽一遍 API,需要做到什麼程度呢?大概就是什麼場景用什麼 API 都能了如于心,再大白話一點就是可以将之前用 `Vue2.x` 寫的代碼,用 `Vue 3` 無差别重構一遍。
推薦一下本人近期維護的開源項目:
Spring Boot 開源電商項目(含商城端和背景管理系統):https://github.com/newbee-ltd/newbee-mall
Spring Boot + Vue3 前後端分離商城項目:https://github.com/newbee-ltd/newbee-mall-vue3-app
Vue 3.0 + Vite 2.0 + Vue-Router 4.0 + Element-Plus + Echarts 5.0 + Axios 開發的背景管理系統:https://github.com/newbee-ltd/vue3-admin
Vue 3
出來之後,很多人有如下想法,“又要學新東西啦”、“我學不動了”等等。
但是事物總有它的兩面性,前端知識更新的很快,利好勤奮好學的同學。計算機行業的疊代速度很快,前端在計算機領域裡,算是前浪被拍在沙灘上比較快的。
我很羨慕還在學校的同學,因為現在的大學生,資訊的擷取量比我當年在大學的時候大得多,我希望你們能珍惜這樣的機會,好好的學習新知識,希望你們進入社會不要被毒打。
學習一門新的技術,我認為最好的方式就是通過 Demo 去制造使用場景,通覽一遍 API,需要做到什麼程度呢?
大概就是什麼場景用什麼 API 都能了如于心,再大白話一點就是可以将之前用
Vue2.x
寫的代碼,用
Vue 3
無差别重構一遍。
建構 Vue3.0 的三種方式
就目前而言,建構
Vue 3
的項目有三種方式。
1、指令行工具 (CLI)
對于
Vue 3
,你應該使用
npm
上可用的 Vue CLI v4.5 作為
@vue/cli@next
。要更新,你應該需要全局重新安裝最新版本的
@vue/cli
:
yarn global add @vue/cli@next
# OR
npm install -g @vue/cli@next
2、Vite
Vite
是一個 web 開發建構工具,由于其原生 ES 子產品導入方法,它允許快速提供代碼。
通過在終端中運作以下指令,可以使用 Vite 快速設定 Vue 項目。
使用 npm:
npm init vite-app <project-name>
cd <project-name>
npm install
npm run dev
3、Webpack
很早的時候,Vue-CLI 還沒支援
Vue 3
項目的建立,Vue 團隊制作了一個 Webpack 的項目配置放在 Github,可以直接克隆下來使用。
git clone https://github.com/vuejs/vue-next-webpack-preview.git demov3
cd demov3
npm install
npm run dev
不推薦使用這種方式,現在都有上面兩種了~~
(以前看星星看月亮的時候叫人家“小甜甜”,現在新人勝舊人,叫人家“牛夫人”)
代碼實踐
我們選擇比較新鮮的 Vite 去建構項目,要玩就玩最潮的。我的本地 Node 版本是
v12.6.0
,盡量保持一緻。
建構項目
npm init vite-app todo-v3
cd todo-v3
npm install // 建議使用淘寶鏡像 cnpm install
npm run dev
啟動之後如下所示,代表成功了:
入口頁面
首先映入眼簾的是
main.js
的變化:
// Vue 3.0
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
// Vue 2.x
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
第一段代碼是
Vue 3
的建立 Vue 執行個體形式,通過
createApp
的形式,你别說,和
React
真的挺像的😄。
第二段是
Vue 2.x
的建立 Vue 執行個體形式,通過 new 的形式建立。
添加路由 Vue-Router
截止目前,
vue-router-next
更新到了
v4.0.0-beta.12
版本。
你如果用
cnpm install vue-router
安裝路由,是會下載下傳到
vue-router 3.x
的版本,我們需要使用:
cnpm install vue-router@next -S
安裝完畢之後,我們開始配置項目路由,在
src
目錄下建立
rourer
檔案夾,在檔案夾下建立
index.js
檔案,添加如下内容:
import {createRouter, createWebHashHistory} from 'vue-router'
export default createRouter({
history: createWebHashHistory(),
routes: []
})
Vue 2.x 的路由模式通過 mode 選項為 history 或 hash 去控制。
而在 Vue 3 中,通過
createRouter
建立路由執行個體,history 屬性作為控制路由模式的參數,
createWebHashHistory
方法傳回的是 hash 模式,
createWebHistory
傳回的是 history 模式,本項目采用 hash 模式。
同樣,我們需要在
mian.js
中引入
router
執行個體:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './index.css'
createApp(App).use(router).mount('#app')
添加全局狀态 Vuex
vuex
v4.0.0-beta.4
版本,是以我們需要用如下指令安裝:
cnpm i vuex@next -S
接下來在
src
目錄下建立
store
檔案夾,再建立
index.js
檔案,添加代碼如下:
// Vue 3
import { createStore } from 'vuex'
export default createStore({
state() {
return {
author: "十三",
};
},
});
對比 Vue 2.x 寫法:
// Vue 2.x
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
actions,
modules: {}
})
同樣是使用新的寫法,通過
vuex
内部抛出的
createStore
方法,建立一個
Vuex
執行個體。
接下來我們将它引入到
main.js
中:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './index.css'
// 鍊式調用
createApp(App).use(router).use(store).mount('#app')
引入 Antd for Vue3 版本元件庫
Antdv2.x是唐金州老師(杭州校寶線上)研發的新一代适配 Vue 3.0 的元件庫,我們來嘗嘗鮮,這邊我們通過如下指令後下載下傳:
cnpm i --save ant-design-vue@next -S
在
mian.js
内引入
ant-design-vue
元件如下所示:
import { createApp } from 'vue'
import Antd from 'ant-design-vue';
import App from './App.vue'
import router from './router'
import store from './store'
import 'ant-design-vue/dist/antd.css';
import './index.css'
// 本教程采用的是全局引入元件庫
createApp(App).use(router).use(store).use(Antd).mount('#app')
測試一下是否成功,順便解釋一下 Vue 3 如何聲明變量,以及如何通過方法改變變量,代碼如下:
<template>
<a-button @click="add" type="primary">
點我加{{ count }}
</a-button>
<a-button @click="add2('a')" type="primary">
點我加a{{ state.a }}
</a-button>
<a-button @click="add2('b')" type="primary">
點我加b{{ state.b }}
</a-button>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
setup() {
const count = ref(0)
const state = reactive({
a: 0,
b: 0,
})
const add = () => {
count.value += 1
}
const add2 = (type) => {
state[type] += 1
}
return {
state,
count,
add,
add2
}
}
}
</script>
如上述代碼所示,Vue 3 新增的
setup
方法,颠覆了之前傳統的
options
屬性方式,我們可以将業務邏輯都寫在
setup
方法中。
我們有兩種聲明變量的形式:
- ref:它用于聲明簡單的基礎類型變量,如單個數字、boolean、字元串等等。
- reactive:它用于對象引用類型的複雜變量。
所有聲明好的變量和方法,如果想在
template
模闆裡使用的話,必須在
setup
方法裡
return
,否則無法調用。記住傳回什麼就是聲明,如傳回
count
,模闆中就用
{{ count }}
,傳回
state
,模闆中就使用
{{ state.a }}
。效果如下所示:
待辦事項 TODO
首先我們建立
views
檔案夾用于放置頁面元件,在
views
内建立
todo.vue
檔案,如下所示:
<template>
<div id="components-layout-demo-basic">
<a-layout>
<a-layout-header>待辦事項</a-layout-header>
<a-layout-content>内容</a-layout-content>
</a-layout>
</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
setup() {
}
}
</script>
<style scoped>
#components-layout-demo-basic {
min-height: 100vh;
max-width: 40%;
margin: 0 auto;
background-color: #ededed;
}
#components-layout-demo-basic .ant-layout-header,
#components-layout-demo-basic .ant-layout-footer {
background: #7dbcea;
text-align: center;
color: #fff;
}
</style>
引入
antd-v
的布局元件,再給一些基礎樣式。
然後前往
App.vue
和
router/index.js
做如下改動:
// App.vue
<template>
<router-view></router-view>
</template>
<script>
export default {
name: 'App'
}
</script>
import {createRouter, createWebHashHistory} from 'vue-router'
export default createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/todo',
component: () => import('../views/todo.vue')
}
]
})
最後頁面出現如下所示,代表配置成功:
添加新增待辦事項輸入框:
<template>
<div id="components-layout-demo-basic">
<a-layout>
<a-layout-header>待辦事項</a-layout-header>
<a-layout-content>
<a-input-search
v-model:value="todo"
placeholder="請輸入要代辦的事項"
size="large"
@search="addTodo"
>
<template v-slot:enterButton>
<a-button>新增</a-button>
</template>
</a-input-search>
</a-layout-content>
</a-layout>
</div>
</template>
<script>
import { ref, reactive } from 'vue'
import { ref, reactive } from 'vue'
export default {
setup() {
const todo = ref('')
const addTodo = (value) => {
console.log(value)
}
return {
todo,
onSearch
}
}
}
</script>
如下圖所示:
添加“待辦事項”和“已辦事項”模闆,代碼如下:
<template>
<div id="components-layout-demo-basic">
<a-layout>
<a-layout-header>待辦事項</a-layout-header>
<a-layout-content>
<a-input-search
v-model:value="todo"
placeholder="請輸入要代辦的事項"
size="large"
@search="addTodo"
>
<template v-slot:enterButton>
<a-button>新增</a-button>
</template>
</a-input-search>
<h2 class="title">待辦事項</h2>
<a-card title="标題">
<template v-slot:extra>
<a-switch />
</template>
内通
</a-card>
<h2 class="title">已辦事項</h2>
<a-card title="标題">
<template v-slot:extra>
<a-switch />
</template>
内通
</a-card>
</a-layout-content>
</a-layout>
</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
setup() {
const todo = ref('')
const addTodo = (value) => {
console.log(value)
}
return {
todo,
onSearch
}
}
}
</script>
<style scoped>
#components-layout-demo-basic {
min-height: 100vh;
max-width: 40%;
margin: 0 auto;
background-color: #ededed;
}
#components-layout-demo-basic .ant-layout-header,
#components-layout-demo-basic .ant-layout-footer {
background: #7dbcea;
color: #fff;
text-align: center;
}
.title {
margin: 0;
padding: 10px;
}
</style>
效果如下:
接下來我們來添加代辦的相應邏輯:
<template>
<div id="components-layout-demo-basic">
<a-layout>
<a-layout-header>待辦事項</a-layout-header>
<a-layout-content>
<a-input-search
v-model:value="todo"
placeholder="請輸入要代辦的事項"
size="large"
@search="addTodo"
>
<template v-slot:enterButton>
<a-button>新增</a-button>
</template>
</a-input-search>
<h2 class="title">待辦事項</h2>
<a-card :title="`${index + 1}、${item.time}`" v-for="(item, index) in todos" :key="item.id">
<template v-slot:extra>
<a-switch v-model:checked="item.done" @change="handleCheck(item, true)" />
</template>
{{ item.content }}
</a-card>
<h2 class="title">已辦事項</h2>
<a-card :title="`${index + 1}、${item.time}`" v-for="(item, index) in dones" :key="item.id">
<template v-slot:extra>
<a-switch v-model:checked="item.done" @change="handleCheck(item, false)" />
</template>
内通
</a-card>
</a-layout-content>
</a-layout>
</div>
</template>
<script>
import { ref, reactive, computed } from 'vue'
export default {
setup() {
const todo = ref('')
const time = `${new Date().getFullYear()}-${new Date().getMonth()}-${new Date().getDate()}`
const state = reactive({
todoList: [
{
id: 1,
done: false,
time: time,
content: '前往老八食堂,共進午餐'
},
{
id: 2,
done: false,
time: time,
content: '和giao哥合唱一曲'
},
{
id: 3,
done: false,
time: time,
content: '做點陽間的需求'
}
]
})
// 添加待辦事項
const addTodo = (value) => {
if(!value) {
message.error('請輸入待辦事項')
return
}
state.todoList.push({
content: value,
id: Date.now(),
time: time,
done: false
})
todo.value = ''
}
// 通過計算屬性,計算出生成的代辦事項清單
const todos = computed(() => {
return state.todoList.filter(item => !item.done)
})
// 通過計算屬性,計算出生成的已辦清單
const dones = computed(() => {
return state.todoList.filter(item => item.done)
})
// 修改狀态方法
const handleCheck = (item ,status) => {
item.done = status
}
return {
todo,
addTodo,
state,
todos,
dones,
handleCheck
}
}
}
</script>
<style scoped>
#components-layout-demo-basic {
min-height: 100vh;
max-width: 40%;
margin: 0 auto;
background-color: #ededed;
}
#components-layout-demo-basic .ant-layout-header,
#components-layout-demo-basic .ant-layout-footer {
background: #7dbcea;
color: #fff;
text-align: center;
}
.title {
margin: 0;
padding: 10px;
}
</style>
setup
内使用
computed
方法,接收一個回調函數,回調函數内的變量都會被監聽,比如上述
state.todoList
已經被監聽了,我們在
handleCheck
方法内修改待辦事項的狀态,也會被
computed
監聽,是以就會重新整理
template
模闆,效果如下:
總結
Vue 3.0 還有很多值得我們探索的知識,上述内容隻是簡單的教大家如何入門搭建一個項目,并且如何通過新的 API 去結合元件庫進行實踐,後續我也會繼續整理其他的實踐技巧,源代碼已經開源到 GitHub vue3-examples倉庫中,倉庫位址:https://github.com/newbee-ltd/vue3-examples,此倉庫将不定期更新各種 Vue3.0 相關的知識及各種整合 Demo 及 Vue3 使用小技巧,大家可以關注一下,有什麼建議也歡迎大家給我留言。
我曾七次鄙視自己的靈魂:
第一次,當它本可進取時,卻故作謙卑;
第二次,當它空虛時,用愛欲來填充;
第三次,在困難和容易之間,它選擇了容易;
第四次,它犯了錯,卻借由别人也會犯錯來寬慰自己;
第五次,它自由軟弱,卻把它認為是生命的堅韌;
第六次,當它鄙夷一張醜惡的嘴臉時,卻不知那正是自己面具中的一副;
第七次,它側身于生活的污泥中雖不甘心,卻又畏首畏尾。