vue的重要性可想而知,提前學習vue3.0,沒毛病。本文會帶大家瞭解vue3.0的構建工程、antd引入、生命週期、data雙向數據綁定使用、方法使用、計算屬性、監聽、組件引入、組件傳值、路由傳值等知識點,本人菜鳥,大佬多多指導。廢話少說,通過實操做一個登錄、列表、詳情界面直接上代碼。
github源碼: https://github.com/parchments/vue3-admin-template
效果預覽:登錄頁、首頁、列表頁、詳情頁
首頁
列表頁
詳情頁
1、項目搭建
- 安裝node就不說咯,必備。此外需要安裝vue-cli4代以上最新腳手架,可以通過執行如下npm 命令安裝/更新腳手架版本
腳手架升級: npm update @vue/cli
初次安裝: npm i @vue/cli -g
根據自己需求選擇需要預先安裝的插件
vue create \[projectName\]
怎麼知道自己正確安裝了vue3.0,請看vue3.0的main.js,vue2.0引入vue是import Vue from 'vue',vue3.0則是解構引入,看到解構引入代表此項目爲vue3.0,幹得漂亮,繼續。。。
vue3.0全局掛載http、api、config
順便提一句,如果vue3.0+ts開發的話,全局掛載需要如下掛載方式
在文件 main.ts 添加 帶有 + 符號後代碼
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
\+ import axios from "axios";
const app = createApp(App);
\+ app.config.globalProperties.$http = axios;
app.mount("#app")
在文件 shims-vue.d.ts添加 帶有 + 符號後代碼
// shims-vue.d.ts
declare module "*.vue" {
import { defineComponent } from "vue";
const component: ReturnType<typeof defineComponent>;
export default component;
}
\+ declare module "@vue/runtime-core" {
\+ import { AxiosInstance } from "axios";
\+ interface ComponentCustomProperties {
\+ $http: AxiosInstance;
\+ }
\+ }
2、安裝並引入antd
$ npm i --save ant-design-vue@next
//需要按需引入的話安裝插件 babel-plugin-import 然後配置 babel.config.js$ npm i --save babel-plugin-import
完整引入
import { createApp } from 'vue';
import Antd from 'ant-design-vue';
import App from './App';
import 'ant-design-vue/dist/antd.css';
const app = createApp();
app.config.productionTip = false;
app.use(Antd);
以上代碼便完成了 Antd 的引入。需要注意的是,樣式文件需要單獨引入。
**局部導入組件**
import { createApp } from 'vue';
import { Button, message } from 'ant-design-vue';
import App from './App';
const app = createApp();
app.config.productionTip = false;
/\* Automatically register components under Button, such as Button.Group */
app.use(Button);
app.config.globalProperties.$message = message;
如果需要按需加載,則配置`ant-design-vue`
根目錄打開`babel.config.js`文件,將裏面的內容修改爲
module.exports = {
presets: \["@vue/cli-plugin-babel/preset"\],
plugins: \[
//以下是配置按需加載
\[
"import",
{
libraryName: "ant-design-vue",
libraryDirectory: "es",
style: "css"//爲true時加載的是less文件
}
\]
\]
}
目前我是用全局引入的方式引入antd,大家根據自己需求引入即可。
3、頁面佈局
app.vue頁面
<template>
<div id="app">
<router-view/>
</div>
</template>
<style lang="less">
#app {
text-align: center;
}
</style>
login頁面: 涉及data定義,響應式數據、生命週期、方法調用、實例獲取(即是vue2.x的this)
//login
<template>
<div class="box">
<h1>登錄</h1>
<h2>{{name}}</h2>
<a-form class="form" layout="inline">
<a-form-item label="賬號">
<a-input v-model:value="account" type="text" placeholder="請輸入賬號"/>
</a-form-item>
<a-form-item label="密碼">
<a-input v-model:value="password" type="password" placeholder="請輸入密碼"/>
</a-form-item>
<h3>輸入賬號密碼,{{count}} 秒後登錄</h3>
<a-button @click="login()" block :disabled="account === '' || password === ''" type="primary">登錄</a-button>
</a-form>
</div>
</template>
<script>
//vue-cli 4.5.4創建的3.0
// import { reactive } from '@vue/composition-api' //會提示報錯 export 'default' (imported as 'Vue') was not found in 'vue'
import { reactive, toRefs, getCurrentInstance, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured} from 'vue' //vue-cli 4.5.4 之後vue3.0集成了@vue/composition-api
export default {
name: 'login',
components: {
},
//始化數據,介於beforeCreate與created之間,相當於beforeCreate、created的合併
setup() {
//setup(props,context)函數 默認兩個屬性props,context 屬性和上下文 setup函數中無法訪問到this
//創建處理響應式數據對象 類似date 需要先導入
const state = reactive({
count: 3,
name: '我是響應式數據name',
account: '',//賬號
password: ''//密碼
})
//獲取當前路由實例
//Vue 3.0 中通過 getCurrentInstance 方法獲取當前組件的實例,然後通過 ctx 屬性獲得當前上下文,ctx.$router 是 Vue Router 實例,裏面包含了 currentRoute 可以獲取到當前的路由信息
const { ctx } = getCurrentInstance();
console.log(toRefs)
//登錄方法
const login = () => {
// state.count++;
console.log(ctx);
let {account,password} = state;//對象解構
if(account=== "" || password===""){
alert('賬號密碼不能爲空')
}else{
setInterval(()=>{
state.count--;
},1000)
setTimeout(()=>{
ctx.$router.push('/index');
},3000);
}
// return
}
//以下是生命週期
//組件掛載前
onBeforeMount( () => {
console.log('onBeforeMount,組件掛載前,相當於beforeMount')
})
//實例掛載完畢
onMounted( () => {
console.log('onMounted,實例掛載完畢,相當於mounted')
})
//響應式數據變化前
onBeforeUpdate( () => {
console.log('onBeforeUpdate,響應式數據變化前,相當於beforeUpdate')
})
//響應式數據變化完成
onUpdated( () => {
console.log('onUpdated,響應式數據變化完成 ,相當於updated')
})
//實例銷燬前
onBeforeUnmount( () => {
console.log('onBeforeUnmount,實例銷燬前 ,相當於beforeDestroy')
})
//實例已銷燬
onUnmounted( () => {
console.log('onUnmounted,實例已銷燬 ,相當於destroyed')
})
//錯誤數據捕捉
onErrorCaptured( () => {
console.log('onErrorCaptured,錯誤數據捕捉')
})
//setup函數的返回值 導出
return {
//...state, //如果沒有用toRefs方法的話,是不能把reactive創建出來的數據變成響應式數據的 需要響應式就是要加上toRefs 否則不需要
...toRefs(state),//把reactive創建出來的數據變成響應式數據
login
}
}
}
</script>
<style lang="less" scoped>
.box{
width: 50%;
margin: 0 auto;
padding-top: 200px;
.form{
width: 60%;
margin: 0 auto;
padding-top: 30px;
}
}
</style>
看得出來跟vue2.x的結構已經有很大區別了,例如setup、方法使用等等,setup是Composition API的入口,Vue3.0提供的新屬性,可以在setup中使用Composition API,在上文代碼中我們在setup中通過reactive初始化了一個響應式數據,然後通過return返回了一個對象,對象中包含了聲明的響應式數據和一個方法。
setup函數有兩個參數,分別是props和context, setup(props,context);
props組件外部傳入進來的屬性
export default {
props: {
title: {
type: String
}
},
setup(props) {
//組件傳入的值
console.log(props.title)
}
}
context是一個對象,裏面包含了三個屬性,分別是 attrs、slots、emit
attrs與Vue2.0的this.$attrs是一樣的,即外部傳入的未在props中定義的屬性。對於attrs與props一樣,我們不能對attrs使用es6的解構,必須使用attrs.name的寫法。
slots對應的是組件的插槽,與Vue2.0的this.$slots是對應的,與props和attrs一樣,slots也是不能解構的。
emit對應的是Vue2.0的this.$emit, 即對外暴露事件。
home.vue頁面
![](https://oscimg.oschina.net/oscnet/up-0e5c5181a088f6b3bd925effb7caf816720.png)
<template>
<div>
<Nav />
<router-view></router-view>
<br/>
<br/>
<br/>
<br/>
<a-button @click="back()">退出登錄</a-button>
</div>
</template>
<script>
// import { reactive } from '@vue/composition-api' //會提示報錯 export 'default' (imported as 'Vue') was not found in 'vue'
import { reactive,toRefs,getCurrentInstance } from 'vue' //vue-cli 4.5.4 之後vue3.0集成了@vue/composition-api
import Nav from '../../components/nav.vue'
export default {
name: 'home',
components: {
Nav
},
//始化數據,介於beforeCreate與created之間,相當於beforeCreate、created的合併
setup(props,context) {
console.log(props,context);
//函數 默認兩個屬性props,context 屬性和上下文 setup函數中無法訪問到this
//創建處理響應式數據對象 類似date 需要先導入
const state = reactive({
})
//獲取當前路由實例
//Vue 3.0 中通過 getCurrentInstance 方法獲取當前組件的實例,然後通過 ctx 屬性獲得當前上下文,ctx.$router 是 Vue Router 實例,裏面包含了 currentRoute 可以獲取到當前的路由信息
const { ctx } = getCurrentInstance();
//登錄方法
const back =() => {
ctx.$router.push('/login');
}
//setup函數的返回值 導出
return {
...toRefs(state),
back
}
}
}
</script>
index->index.vue頁面
<template>
<div style="padding-top: 100px;">
<h2>首頁內容</h2>
<img src="../../../assets/logo.png" alt="">
</div>
</template>
<script>
import { reactive, toRefs, getCurrentInstance } from 'vue'
export default {
name: 'index',
// components: {
// },
setup() {
const state = reactive({
})
//獲取當前路由實例
const { ctx } = getCurrentInstance();
console.log(ctx)
//setup函數的返回值 導出
return {
...toRefs(state)
}
}
}
</script>
accountList.vue 列表頁面(計算屬性)
<template>
<div style="margin-top: 100px;">
<ti :title="title"></ti>
<h3>列表請求數據中...{{count}}秒後顯示</h3>
<a-table :data-source="list" :pagination="false" style="width: 60%; margin: 0 auto 30px;">
<a-table-column key="account" title="account" data-index="account" />
<a-table-column key="password" title="password" data-index="password" />
<a-table-column key="action" data-index="action">
<template v-slot="{record}">
<span>
<a @click="goToLink(record.id)">詳情</a>
</span>
</template>
</a-table-column>
</a-table>
<a-input type="text" v-model:value="leftValue" placeholder="leftValue" style="width: 100px;"/>
<a-input type="text" v-model:value="rightValue" placeholder="rightValue" style="width: 100px;"/>
<div>
計算屬性輸出的結果是:{{resultValue}}
</div>
<!\-\- <div>
<h2>Clicked {{ count }} times</h2>
<h2>Watch Count is {{ watchCount }}</h2>
<button @click="increase">Click</button>
</div> -->
</div>
</template>
<script>
import {
reactive,
toRefs,
getCurrentInstance,
onMounted,
computed
} from 'vue'
import title from './component/title.vue'
export default {
name: 'accountList',
components: {
'ti': title
},
setup(props, context) {
console.log('propss,context', props, context)
const state = reactive({
title: '我是子組件的值', //子組件
list: \[\],
count: 3,
leftValue: 0,
rightValue: 0,
//計算屬性
resultValue: computed(() => {
return Number(state.leftValue) + Number(state.rightValue);
})
})
// const count1 = ref(0);
// const watchCount = ref(0);
// function increase () {
// count1.value++;
// };
// watch( () => count1.value,
// (val) => {
// watchCount.value = val;
// }
// );
//獲取當前路由實例
const {
ctx
} = getCurrentInstance();
console.log('列表實例', ctx)
function goToLink(index) {
ctx.$router.push({
path: '/accountList/detail',
query: {
id: index
}
})
}
function getList() {
// axios請求
let timer1 = setInterval(() => {
state.count--;
if (state.count < 1) {
clearInterval(timer1)
return
}
}, 1000)
console.log('請求列表數據')
//模擬異步請求
let timer2 = setTimeout(() => {
state.list = \[{
id: 1,
account: 'admin',
password: '111111'
},
{
id: 2,
account: 'chushi',
password: 'chushi-111'
},
{
id: 3,
account: 'six',
password: '666'
}
\]
clearTimeout(timer2)
}, 2000)
//以下爲普通列表請求方法
// async getList(params) {
// state.loading = true;
// try{
// let res = await ctx.$api.systemManage.getList(params);
// if (res.data.retcode === ctx.$config.RET\_CODE.SUCCESS\_CODE) {
// let data = res.data.data;
// if (data.length > 0) {
// state.tableData = data;
// state.paginationParams.pageSize = data.pageSize; //每頁的數量
// state.paginationParams.size = data.size; //當前頁的數量
// state.paginationParams.total = data.total; //總條數
// state.paginationParams.pages = data.pages; //總頁碼數
// } else {
// state.tableData = \[\];
// }
// } else {
// ctx.$Message.error('請求成功,暫無數據');
// }
// state.loading = false;
// }catch(e){
// state.loading = false;
// ctx.$Message.error('暫無數據');
// console.log(e);
// }
// }
}
onMounted(() => {
getList();
})
//setup函數的返回值 導出
return {
...toRefs(state),
goToLink,
}
}
}
</script>
detail 詳情頁面(路由傳參)
<template>
<div>
<h3>請求參數id爲{{id}}的數據</h3>
<router-link to="/accountList">返回列表</router-link>
</div>
</template>
<script>
import { reactive, toRefs, getCurrentInstance } from 'vue'
import { useRoute } from 'vue-router'
export default {
name: 'detail',
components: {
},
setup(props,context) {
const state = reactive({
id: ''
})
const { ctx } = getCurrentInstance();//獲取實例
const { query } = useRoute();//獲取路由參數
console.log(query)
state.id = query.id;
console.log('詳情',ctx,context)
//setup函數的返回值 導出
return {
...toRefs(state)
}
}
}
</script>
相信大家對vue3.0基礎用法有了初步的認識,菜鳥的我也在不斷學習中,持續更新ing