vue3 + element-plus + typescript 创建系统

vue3 构建项目是在没阅读官网文档和其他资料的情况下,一边试验一边摸索学习的,如果有不正确的地方,欢迎评论指正~

项目搭建

vue3 安装

1、安装 nodeJS
2、安装 vue-cli

npm install -g @vue/cli

# 检测是否安装成功(显示版本号即为安装成功)
vue --version

创建项目

vue create [项目名]

直接选第一个:
vue3 + element-plus + typescript 创建系统_第1张图片
或者选择第三个进行自定义配置:
vue3 + element-plus + typescript 创建系统_第2张图片
vue3 + element-plus + typescript 创建系统_第3张图片
vue3 + element-plus + typescript 创建系统_第4张图片

运行项目

npm run serve

默认端口是8080
vue3 + element-plus + typescript 创建系统_第5张图片

路由设置

安装router

没有自定义安装 router,需要进行安装:

npm install vue-router@4

main.ts文件需要引入router模块

// main.ts
import App from './App.vue';
import router from './router';

createApp(App).use(router).mount("#app");

配置路由

路由配置写在srt/router目录下的index.ts文件中,如果没有这个文件,可以自行创建
vue3 + element-plus + typescript 创建系统_第6张图片

// index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import HomeView from '../views/HomeView.vue'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',		// 路径
    name: 'home',	// 路由名称
    component: HomeView,	// 对应的路由页面
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

设置统一模板 layout

新增 layout 文件

src目录下新增文件夹layout,新增默认布局文件DefaultLayout.vue
vue3 + element-plus + typescript 创建系统_第7张图片

<template>
    <div class="layout">
        <el-container style="height:100%">
            <el-aside class="layout_aside">
                <el-menu
                    :router="true"
                    :default-active="$route.meta.id"
                >
                    <template v-for="(item, index) in menuList[1].children" :key="index">
                        <el-menu-item :index="item.meta.id" :route="item" v-if="item.meta.isMenu">
                            <el-icon><component :is="item.meta.icon">component>el-icon>
                            <span>{{item.meta.title}}span>
                        el-menu-item>
                    template>
                el-menu>
            el-aside>
            <el-container>
				<router-view />		
            el-container>
        el-container>
    div>
template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
import {
    Document,
    Menu as IconMenu,
    Location,
    Setting,
    Expand,
    ArrowDown,
    SwitchButton,
    Fold,
    Guide,
    Coin,
    Connection,
    Calendar
} from "@element-plus/icons-vue";

@Options({
    components: {
        Document,
        IconMenu,
        Location,
        Setting,
        Expand,
        Fold,
        SwitchButton,
        ArrowDown,
        Guide,
        Coin,
        Connection,
        Calendar
    },
})
export default class DefaultLayout extends Vue {
    isCollapse: Boolean = true; // 菜单栏是否折叠:false--展开 true--折叠

    handleOpen(key: string, keyPath: string[]) {}
    handleClose(key: string, keyPath: string[]) {
        console.log(key, keyPath);
    }

    // 折叠/展开菜单栏
    collapseHandle(): void {
        this.isCollapse = !this.isCollapse;
    }
    // 菜单栏
    get menuList() {return this.$router.options.routes}

    // 退出登录
    logout():void {
        console.log("退出登录");
    }

    mounted() {
        // console.log("路由====", this.menuList, this.$route);
    }

}
script>

配置路由信息

将布局界面DefaultLayout.vue作为父组件,其他界面作为该界面的子组件写在children数组里面

// index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import DefaultLayout from "../layout/DefaultLayout.vue";

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "DefaultLayout",
    component: DefaultLayout,
    children: [
      {
        path: "path",
        component: ()=>import("../views/name.vue"),
        name: "name",
        meta: {			// 路由元信息
          title: "router-title",
          id:"1",
          icon: "guide",
        }
      },
    ]
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

关于菜单的一些问题

动态加载菜单栏 icon

很多时候,系统的菜单都是根据后台配置的,还有权限配置等,菜单前面添加 icon 区分就需要动态引入图标。而 element-plus 是将名字作为标签显示,如在这里插入图片描述的写法是


<el-icon :size="size" :color="color">
  <Edit />
el-icon>


<i class="el-icon-edit">i>

动态引入的写法是在el-icon标签中添加标签,并将 icon 名字写在is属性中:


<el-icon><component :is="item.meta.icon">component>el-icon>

关于菜单高亮与地址栏地址相匹配

vue3 + element-plus + typescript 创建系统_第8张图片

数据响应式

reactive

要为 JavaScript 对象创建响应式状态,可以使用reactive方法:

<script setup lang="ts">
import { reactive } from "vue";

let form = reactive({
  name: "张三",
  age: 11,
  gender: "male",
  phone: "133******"
})
form.name = "李四"
console.log("form 没变:", form);

let obj = {
  name: "东子",
  age: 22,
  gender: "female",
  phone: "122******"
}
form = obj;
console.log("form 后变:", form);
</script>

reactive在控制台打印出来的是proxy
vue3 + element-plus + typescript 创建系统_第9张图片

方法更新数据

如果是在script标签的全局下修改form的值,界面是可以响应的,但是如果用按钮控制信息的改变,界面是没有变化的:vue3 + element-plus + typescript 创建系统_第10张图片
vue3 + element-plus + typescript 创建系统_第11张图片
在方法内form = obj这种写法是不生效的,需要用到Object.assign(form, obj),界面才会更新数据vue3 + element-plus + typescript 创建系统_第12张图片
vue3 + element-plus + typescript 创建系统_第13张图片

解构

如果是reactive需要用到解构,需要用toRefs

let form = reactive({
  name: "张三",
  age: 11,
  gender: "male",
  phone: "133******"
})

let { name, age, gender, phone } = form;
name = "李四";

console.log("name:", name);
console.log("age:", age);
console.log("gender:", gender);
console.log("phone:", phone);

vue3 + element-plus + typescript 创建系统_第14张图片

import {reactive, toRefs} from 'vue';

let form = reactive({
  name: "张三",
  age: 11,
  gender: "male",
  phone: "133******"
})
let { name, age, gender, phone } = toRefs(form);
name.value = "李四";

console.log("name:", name.value);
console.log("age:", age.value);
console.log("gender:", gender.value);
console.log("phone:", phone);

vue3 + element-plus + typescript 创建系统_第15张图片

ref

接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。获取和修改需要通过.value属性进行:

import {ref} from 'vue';

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

computed 和 watch 使用

computed

computed获取的值需要加.value

import { ref, computed } from "vue";

const count = ref(1)

// 只有 get 获取数据
const num = computed(()=>{
	return count.value + 1;
})
console.log("num:", num.value);		// 2


// get 和 set 
const plusOne = computed({
  get: () => count.value + 1,
  set: val => {
    count.value = val - 1
  }
})
console.log("plusOne", plusOne.value);

plusOne.value = 1
console.log(count.value) // 0

vue3 + element-plus + typescript 创建系统_第16张图片

watch

reactive

<template>
  <div class="about">
    <el-input v-model="state.count">el-input>
  div>
template>
import {reactive, watch, ref} from 'vue';

// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log("newVal:", newVal)
    console.log("oldVal:", oldVal)
  },
  {
    deep: true,
    immediate: true
  }
)

在这里插入图片描述

ref

<template>
  <div class="about">
    <el-input v-model="count">el-input>
  div>
template>
const count = ref(3)
watch(count, (newVal, oldVal) => {
  console.log("newVal:", newVal)
  console.log("oldVal:", oldVal)
})

在这里插入图片描述

同时侦听多个源

vue3 + element-plus + typescript 创建系统_第17张图片
vue3 + element-plus + typescript 创建系统_第18张图片

父子组件通信

defineProps

defineProps不需要导入就可以直接使用
vue3 + element-plus + typescript 创建系统_第19张图片
vue3 + element-plus + typescript 创建系统_第20张图片

子组件向父组件传值

getCurrentInstance支持访问内部组件实例。getCurrentInstance 只能在 setup生命周期钩子中调用。

ctx.emit("update:paramName", newValue);	// 可以向父组件传值
ctx.emit("funcName", paramValue);	// 通过调用方法并且向父组件传递参数
第一种

vue3 + element-plus + typescript 创建系统_第21张图片
vue3 + element-plus + typescript 创建系统_第22张图片

第二种

vue3 + element-plus + typescript 创建系统_第23张图片
vue3 + element-plus + typescript 创建系统_第24张图片
但是界面并没有更新,因为vue3中父组件绑定的值需要用到v-model:xxx
vue3 + element-plus + typescript 创建系统_第25张图片
vue3 + element-plus + typescript 创建系统_第26张图片
vscode编译器会显示报错:
vue3 + element-plus + typescript 创建系统_第27张图片

defineExpose

使用

你可能感兴趣的:(Vue.js,typescript,element-plus,vue)