一、 项目地址学习管理系统地址:?https://bushanjiangzi.gitee.io/vue3manage/#/源码地址:https://gitee.com/bushanjiangzi/vue3-element-plus 二、新特性1. 实例化 1 1 import { createApp } from vue2 ...
一、 项目地址
学习管理系统地址:?https://bushanjiangzi.gitee.io/vue3manage/#/
源码地址:https://gitee.com/bushanjiangzi/vue3-element-plus

二、新特性
1. 实例化
1 1 import { createApp } from 'vue'
2 2 import App from './App.vue'
3 3 import router from './router'
4 4 import store from './store'
5 5 import ElementPlus from 'element-plus'
6 6 import 'element-plus/lib/theme-chalk/index.css'
7 7 import './assets/css/public.css'
8 8 import './assets/css/reset.css'
9 9
10 10 createApp(App)
11 11 .use(store)
12 12 .use(router)
13 13 .use(ElementPlus)
14 14 .mount('#app')
2. reactive 和 ref
reactive 类似于vue2.x 中的 Vue.observable(),vue3.x的reactive和ref取代了vue2.x中的data数据定义
reactive和ref取代了vue2.x中的data数据定义 1 <template>
2 <div class="home">
3 <HelloWorld :propsMsg="propsMsg">
4 <template #backBtn>
5 <router-link to="/setup">
6 <el-button type="primary" plain>Setup</el-button>
7 </router-link>
8 </template>
9 </HelloWorld>
10 <h2>HelloWorld Input</h2>
11 <input v-model="myInput" />
12 <h2>Conputed String</h2>
13 <input v-model="firstInput" />
14 <input v-model="secondInput" />
15 <div>{{ state.total }}</div>
16 <h2>Conputed Object</h2>
17 <input v-model="state.first" />
18 <input v-model="state.second" />
19 <div>total:{{ state.total2 }}</div>
20 <div>doubleCount:{{ doubleCount }}</div>
21 </div>
22 </template>
23
24 <script>
25 import HelloWorld from '@/components/HelloWorld.vue'
26 import { reactive, ref, watchEffect, watch, provide, computed } from 'vue'
27 import setupTest from '@/composition/setup'
28
29 export default {
30 name: 'Home',
31 components: {
32 HelloWorld
33 },
34 setup() {
35 const { propsMsg, myInput } = setupTest()
36 propsMsg.name = ' World'
37 const firstInput = ref()
38 const secondInput = ref()
39 const state = reactive({
40 first: 0,
41 second: 0,
42 total: 0,
43 total2: 0
44 })
45 watchEffect(() => {
46 state.total = firstInput.value + secondInput.value
47 state.total2 = parseInt(state.first) + parseInt(state.second)
48 })
49 watch([firstInput, secondInput], (newValues, prevValues) => {
50 console.log(firstInput.value, secondInput.value, newValues, prevValues)
51 })
52 const doubleCount = computed({
53 get() {
54 return state.total2 * 2
55 },
56 set(newVal) {
57 state.total2 = newVal / 2
58 }
59 })
60 provide('provideData', 'provide data from home')
61 return {
62 propsMsg,
63 myInput,
64 firstInput,
65 secondInput,
66 state,
67 doubleCount
68 }
69 }
70 }
71 </script>
3. watch & watchEffect
3.x中watch支持监听单个属性,也支持监听多个属性,相比2.x的watch更灵活,多个时第一个参数是要监听的数组,第二个参数是回调函数,返回参数是新值;3.x中watchEffect方法会返回一个方法(俗称副作用,只要返回函数里的依赖项发生变化就回执行回调函数),watch跟watchEffect不同的地方在于,watchEffect注册后会立即调用,而watch默认不会,除非显示指定immediate=true,并且watchEffect可以停止监听
4. 计算属性 computed
2.x和3.x中的computed都支持getter和setter,写法一样,只是3.x中是组合函数式
5. provide和inject
父组件:provide('provideData', 'provide data from home')
子孙组件:inject('provideData')
1 <template>
2 <div class="hello">
3 <h1 class="left">{{ propsMsg.msg }} {{ propsMsg.name }} {{ homeInput }}</h1>
4 <div class="right">
5 <el-button type="primary" plain @click="toElement">Element-Plus</el-button>
6 <slot name="backBtn"></slot>
7 </div>
8 </div>
9 </template>
10
11 <script>
12 // eslint-disable-next-line
13 import { computed, inject, onMounted, getCurrentInstance } from 'vue'
14 import store from '@/store/index'
15 import router from '@/router/index'
16 import { ElMessage } from 'element-plus'
17 export default {
18 name: 'HelloWorld',
19 props: {
20 propsMsg: {
21 type: Object,
22 require: true
23 }
24 },
25 setup() {
26 const homeInput = computed(() => {
27 return store.state.homeInput
28 })
29 const toElement = () => {
30 router.push({ name: 'ElementIndex' })
31 }
32 ElMessage.success(inject('provideData'))
33 onMounted(() => {
34 // const { ctx } = getCurrentInstance()
35 // ctx.$message.success(inject('provideData'))
36 // console.log(inject('provideData'))
37 })
38 return {
39 homeInput,
40 toElement
41 }
42 }
43 }
44 </script>
6. getCurrentInstance获取当前组件实例
import { getCurrentInstance } from 'vue'
const { ctx } = getCurrentInstance()
7. 插槽slot
父组件:```
????<HelloWorld?:propsMsg="propsMsg"> ??????<template?#backBtn> ????????<router-link?to="/setup"> ??????????<el-button?type="primary"?plain>Setup</el-button> ????????</router-link> ??????</template> ????</HelloWorld>```
子组件:```
<template> ??<div?class="hello"> ????<h1?class="left">{{?propsMsg.msg?}}?{{?propsMsg.name?}}?{{?homeInput?}}</h1> ????<div?class="right"> ??????<el-button?type="primary"?plain?@click="toElement">Element-Plus</el-button> ??????<slot?name="backBtn"></slot> ????</div> ??</div> </template>```
8. 生命周期
3.x移除了2.x中的beforeCreate和created钩子,通过setup方法代替
1 import {
2 onBeforeMount,
3 onMounted,
4 onBeforeUpdate,
5 onUpdated,
6 onBeforeUnmount,
7 onUnmounted
8 } from 'vue'
9
10 export default {
11 setup() {
12 onBeforeMount(() => {
13 console.log('component is onBeforeMount')
14 })
15 onMounted(() => {
16 console.log('component is onMounted')
17 })
18 onBeforeUpdate(() => {
19 console.log('component is onBeforeUpdate')
20 })
21 onUpdated(() => {
22 console.log('component is onUpdated')
23 })
24 onBeforeUnmount(() => {
25 console.log('component is onBeforeUnmount')
26 })
27 onUnmounted(() => {
28 console.log('component is onUnmounted')
29 })
30 }
31 }
三、Composition API
vue2.x中,所有的数据都在data方法中定义返回,方法定义在methods下面,并通过this调用vue3.x中,所有的代码逻辑将在setup方法中实现,包括data、watch、computed、methods、hooks,并且不再有this;vue3.x setup方法在组件生命周期内只执行一次,不会重复执行,相比vue2.x中基于OPTIONS配置的方式,vue3.x基于组合式API的方式语义没有2.x清晰,2.x中data、methods、computed、watch等都通过不同的scope区分开,看起来很清晰,3.x都放在setup方法中,对代码组织能力会有更高的要求。
1 import { reactive, ref, getCurrentInstance } from 'vue'
2
3 const setupTest = function() {
4 const { ctx } = getCurrentInstance()
5 const propsMsg = reactive({
6 msg: 'Hello',
7 name: 'Jiangzi',
8 age: 18
9 })
10 const myInput = ref()
11 const formRef = ref()
12
13 return {
14 ctx,
15 propsMsg,
16 myInput,
17 formRef
18 }
19 }
20
21 export default setupTest
四、router路由
获取路由配置项:
this.$router.options.routes
当前路由组件名:
this.$router.currentRoute.value.name
1 <script>
2 export default {
3 name: 'ElementNav',
4 data() {
5 return {
6 menuList: [],
7 activeName: ''
8 }
9 },
10 created() {
11 this.$router.options.routes.forEach((item) => {
12 if (item.desc === 'element-plus') {
13 this.menuList = item.children
14 }
15 })
16 // console.log(this.menuList)
17 let currentRouteName = this.$router.currentRoute.value.name
18 // console.log(currentRouteName)
19 this.activeName = currentRouteName
20 },
21 mounted() {},
22 methods: {
23 menuClick(item) {
24 this.activeName = item.name
25 },
26 handleOpen(key) {
27 // console.log(key, keyPath)
28 if (key) {
29 this.$router.push({ name: key })
30 }
31 },
32 handleClose(key) {
33 if (key) {
34 this.$router.push({ name: key })
35 }
36 }
37 }
38 }
39 </script>
项目配置页路由
1 // eslint-disable-next-line
2 import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
3 import Home from '@/views/Home.vue'
4 const Test = () => import('@/views/Test.vue')
5 const Setup = () => import('@/views/Setup.vue')
6 const ElementIndex = () => import('@/views/element/ElementIndex.vue')
7 const ElementHome = () => import('@/views/element/ElementHome.vue')
8 const ElementForm = () => import('@/views/element/ElementForm.vue')
9 const ElementTree = () => import('@/views/element/ElementTree.vue')
10 const ElementUpload = () => import('@/views/element/ElementUpload.vue')
11 const ElementTable = () => import('@/views/element/ElementTable.vue')
12 const ElementPages = () => import('@/views/element/ElementPages.vue')
13 const ElementCarousel = () => import('@/views/element/ElementCarousel.vue')
14 const ElementCalendar = () => import('@/views/element/ElementCalendar.vue')
15 const ElementTransfer = () => import('@/views/element/ElementTransfer.vue')
16
17 const routes = [
18 {
19 path: '/',
20 name: 'Home',
21 component: Home
22 },
23 {
24 path: '/test',
25 name: 'Test',
26 // route level code-splitting
27 // this generates a separate chunk (about.[hash].js) for this route
28 // which is lazy-loaded when the route is visited.
29 component: Test
30 },
31 {
32 path: '/setup',
33 name: 'Setup',
34 component: Setup
35 },
36 {
37 path: '/element',
38 name: 'ElementIndex',
39 component: ElementIndex,
40 redirect: '/element/home',
41 desc: 'element-plus',
42 children: [
43 {
44 path: '/element/home',
45 name: 'ElementHome',
46 component: ElementHome,
47 desc: '基础组件',
48 icon: 'el-icon-office-building'
49 },
50 {
51 path: '/element/form',
52 name: 'ElementForm',
53 component: ElementForm,
54 desc: 'Form表单',
55 icon: 'el-icon-message'
56 },
57 {
58 path: '/element/tree',
59 name: 'ElementTree',
60 component: ElementTree,
61 desc: '树形控件',
62 icon: 'el-icon-grape'
63 },
64 {
65 path: '/element/upload',
66 name: 'ElementUpload',
67 component: ElementUpload,
68 desc: '上传组件',
69 icon: 'el-icon-upload2'
70 },
71 {
72 path: '/element/table',
73 name: 'ElementTable',
74 component: ElementTable,
75 desc: 'Table表格',
76 icon: 'el-icon-s-grid'
77 },
78 {
79 path: '/element/pages',
80 name: 'ElementPages',
81 component: ElementPages,
82 desc: 'pages分页',
83 icon: 'el-icon-folder-opened'
84 },
85 {
86 path: '/element/carousel',
87 name: 'ElementCarousel',
88 component: ElementCarousel,
89 desc: '走马灯',
90 icon: 'el-icon-picture'
91 },
92 {
93 path: '/element/calendar',
94 name: 'ElementCalendar',
95 component: ElementCalendar,
96 desc: '日历',
97 icon: 'el-icon-date'
98 },
99 {
100 path: '/element/transfer',
101 name: 'ElementTransfer',
102 component: ElementTransfer,
103 desc: '穿梭框',
104 icon: 'el-icon-d-arrow-right'
105 }
106 ]
107 }
108 ]
109
110 const router = createRouter({
111 // history: createWebHistory(process.env.BASE_URL), // HTML5模式路由
112 history: createWebHashHistory(process.env.BASE_URL), // 哈希路由
113 routes
114 })
115
116 export default router
五、vuex状态管理
1. 提交
? import?store?from?'@/store/index'
??watchEffect(()?=>?{ ????store.commit('setHomeInput',?myInput.value) ??}) 2. 获取 ????const?homeInput?=?computed(()?=>?{ ??????return?store.state.homeInput ????})
1 import { createStore } from 'vuex'
2
3 export default createStore({
4 state: {
5 homeInput: ''
6 },
7 mutations: {
8 setHomeInput(state, data) {
9 state.homeInput = data
10 }
11 },
12 actions: {},
13 modules: {}
14 })
本文标题为:vue3+element-plus开发学习管理系统
- 关于 html:如何从 css 表中删除边距和填充 2022-09-21
- javascript 判断当前浏览器版本并判断ie版本 2023-08-08
- JS实现左侧菜单工具栏 2022-08-31
- vue keep-alive 2023-10-08
- jsPlumb+vue创建字段映射关系 2023-10-08
- 深入浅析AjaxFileUpload实现单个文件的 Ajax 文件上传库 2022-12-15
- 1 Vue - 简介 2023-10-08
- ajax实现输入提示效果 2023-02-14
- 基于CORS实现WebApi Ajax 跨域请求解决方法 2023-02-14
- layui数据表格以及传数据方式 2022-12-13
