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