Vue3浅尝
中文版API文档地址:Vue3中文文档
脚手架文档地址:Vue CLI
本文基于vue-cli@4.5.0
脚手架,vue@3.0.0-0
,typescript
实现。
CHANGELOG
2020-9-30
refactor
1、重构引入ant-design-vue
方式以及写法
2、加上配置git
提交规范说明
脚手架安装
安装
# 全局安装
npm i -g @vue/cli
# 创建项目
vue create vue3-study
# 使用typescript
vue add typescript
配置
vue.config.js
// vue.config.js
const path = require('path');
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
chainWebpack: config => {
// ts
config.module
.rule('ts')
.use('ts-loader')
.loader('ts-loader')
.end()
.use('babel-loader')
.loader('babel-loader')
.end()
.use('cache-loader')
.loader('cache-loader')
.end()
// 配置路径别名
config.resolve.alias
.set('@', resolve('src'))
},
devServer: {
inline: true,
hot: true,
stats: 'minimal',
clientLogLevel: 'warning',
contentBase: __dirname,
overlay: true,
historyApiFallback: true
}
}
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
启动服务
这里也可以通过package.json
修改成自己的命令
yarn serve
具体使用
1. Vue-Router
配套Vue3
的Vue-Router
版本为vue-router@next
1.1 下载配套版本
yarn add vue-router@next
1.2 使用
1.2.1 router
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
// * history对象
const routerHistory = createWebHistory()
// 1. 定义路由组件
// * 1.1 Normal
import Normal from '@/pages/Normal/index.vue';
// * 1.2 Todo
import TodoList from '@/pages/TodoList/index.vue';
// 2. 定义路由
const routes = [{
path: '/',
component: Normal
},
{
path: '/normal',
component: Normal
},
{
path: '/todo',
component: TodoList
}]
// 3. 创建router对象
const router = createRouter(
{
history: routerHistory,
routes
}
)
// 4. 导出对象
export default router;
1.2.2 main.ts
import { createApp } from 'vue'
import router from './router';
import App from './App.vue'
// 创建vue实例
const app = createApp(App)
app.use(router)
app.mount('#app')
1.2.3 App.vue
<template>
<div id="root">
<img src="./assets/logo.png" />
<div id="nav">
<router-link to="/"> Home</router-link>
<router-link to="/normal">Normal </router-link>
<router-link to="/todo">TodoList</router-link>
</div>
<router-view />
</div>
</template>
2. 父子通信
2.2.1 child
// child.vue
<template>
<ul>
<li v-for="(item, index) in todoLists" :key="item.id">
<p>
{{ index + 1 }}、{{ item.name }}
<span class="add" @click="add">新增</span>
<span class="del" @click="del(item.id)" v-if="todoLists.length > 1"
>删除</span
>
</p>
</li>
</ul>
</template>
<script lang="ts">
export default {
props: {
todoLists: Array,
add: Function,
del: Function,
},
};
</script>
<style lang="less" scoped>
ul {
width: 400px;
margin: 0;
padding: 0;
li {
width: 100%;
list-style: none;
text-align: left;
line-height: 20px;
span {
cursor: pointer;
margin: 0 10px;
font-size: 12px;
}
}
}
</style>
2.2.2 father
// index.vue
<template>
<div>
<TodoList :add="add" :del="del" :todoLists="todoLists" />
</div>
</template>
<script lang="ts">
import { reactive } from "vue";
import TodoList from "./TodoList.vue";
export default {
components: { TodoList },
setup() {
const todoLists: { name: string; id: number }[] = reactive([
{
id: 1,
name: "第1件事",
},
]);
// 新增
const add = () => {
const lastId = todoLists[todoLists.length - 1].id;
const newId = lastId + 1;
const newName = `第${newId}件事`;
todoLists.push({
id: newId,
name: newName,
});
};
// 删除
const del = (id: number) => {
let delIndex;
todoLists.forEach((item, index) => {
if (item.id === id) {
delIndex = index;
}
});
delIndex !== undefined && todoLists.splice(delIndex, 1);
};
return {
todoLists,
add,
del,
};
},
};
</script>
3. Vuex
3.1下载配套版本
yarn add vuex@next -D
3.2 使用
3.2.1 新建 store/index.ts
import { createStore } from 'vuex'
export const store = createStore({
state: {
count: 1
},
getters: {
getCount: state => state.count
},
mutations: {
changeCount(state, n: number) {
if (n > 0) {
state.count = n;
}
},
},
actions: {
add({ commit }) {
const count = this.state.count + 1;
commit('changeCount', count)
},
del({ commit }) {
const count = this.state.count - 1;
commit('changeCount', count)
}
}
})
3.2.2 main.ts
import { store } from './store';
app.use(store)
3.2.3 *.vue
<template>
<div class="about">
<h1>warning</h1>
<p><span @click="del">-</span>{{ count }}<span @click="add">+</span></p>
</div>
</template>
<script>
import { useStore } from "vuex";
import { computed } from "vue";
export default {
setup() {
const store = useStore();
const count = computed(() => store.getters["getCount"]);
const add = () => {
store.dispatch("add");
};
const del = () => {
store.dispatch("del");
};
return {
count,
add,
del,
};
},
};
</script>
<style lang="less">
span {
display: inline-block;
background: #eee;
color: #000000;
width: 20px;
height: 24px;
line-height: 24px;
margin: 0 20px;
cursor: pointer;
user-select: none;
}
</style>
4. 生命周期
4.1 生命周期说明
-
取消
beforeCreate
与created
在使用
componsition api
的时候,其实setup
就代替了beforeCreate
与created
,因为setup
就是组件的实际入口函数。 -
beforeDestroy
与destroyed
改名了在
setup
中,beforeDestroy
更名为onBeforeUnmount
,destroyed
更名为onUnmounted
-
将生命周期函数名称变为
on+XXX
,比如mounted
变成了onMounted
,updated
变成了onUpdated
4.2 使用
<script>
import { onMounted, onUpdated, onUnmounted } from "vue";
export default {
setup() {
onMounted(() => {
console.log("mounted!");
});
onUpdated(() => {
console.log("updated!");
});
onUnmounted(() => {
console.log("unmounted!");
});
},
};
</script>