vue3初步使用笔记

最近搭建了一个疫情车辆管理系统,采用的是vue3+Arco Design+vite, 使用起来很不错,特别vite也太快了吧,本文主要记录下vue3vite.


Vite创建应用(vue/react)

npm create vite@latest

Vite配置环境变量

新建环境变量文件

// 开发环境
.env.development
# 必须指定
VITE_MODE_NAME=development
VITE_LOCAL_BASE_API = 'http://192.168.0.155:8090'


// 生产环境
.env.production
# 必须指定
VITE_MODE_NAME=production
VITE_LOCAL_BASE_API = 'http://192.168.0.155:8090'

Axios等文件中引用

import.meta.env.VITE_LOCAL_BASE_API

vite.config.js中引用

import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {

    const env = loadEnv(mode, __dirname)

    return {
        server: {
          host: '0.0.0.0',
          port: '8090',
          proxy: {
            '/api': {
              target: env.VUE_APP_LOCAL_BASE_API,
              rewrite: (path) => path.replace(/^api/, '')
            }
          }
        }
    }
})

Vite配置别名

// vite.config.js

import { resolve } from 'path'

resolve: {
    alias: [{
        find: '@',
            replacement: resolve(__dirname, 'src')
     }]
},

Vite配置局域网访问

vite.config.js中配置server

// vite.config.js

server: {
    host: '0.0.0.0',
    port: '8090',
}

vite更多配置项文档

https://vitejs.dev/config/


vue3使用scss

安装

npm i sass -D

配置vite.config.js

// 全局css
css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "./src/assets/reset.scss";`,
      }
    }
  }

此时 全局css会不生效

解决办法:

app.vue中 随便写个样式即可, lang=scss

<style lang="scss">
a{
    // do something
}
</style>

Vue3使用JSX

安装@vitejs/plugin-vue-jsx

npm i @vitejs/plugin-vue-jsx -D

配置vite.config.js

import vueJsx from '@vitejs/plugin-vue-jsx'
import { defineConfig, loadEnv } from 'vite'


export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, __dirname)
  return {
    plugins: [vue(), vueJsx({})],
   }
})

使用:

script 标签一定要加 lang="jsx"

<script setup lang="jsx">
render: () => {
    return (
        <>
            <dx-button status="warning" type="text">编辑</dx-button>
            <dx-button status="danger" type="text">删除</dx-button>
        </>
    )
}
</script>

router

基本和vue2中使用区别不大

安装

npm i vue-router@4 -S

配置 router/index.js

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

const routes = [
  {
    path: "/",
    redirect: 'home',
    component: Layout,
    children: [
      {
        path: '/home',
        name: 'home',
        component: () => import('../views/index.vue'),
        meta: {
          title: "首页"
        }
      },
      {
        path: '/404',
        name: '404',
        component: () => import('../views/error/404.vue'),
        meta: {
          title : '404 not found'
        }
      },
    ]
  },
]

export default createRouter({
  history: createWebHistory(),
  routes,
});

挂载到main.js

import { createApp } from 'vue';
import App from './App.vue';
import router from './routers';

const app = createApp(App)
app.use(router)
app.mount("#app")

配置挂载点:

app.vue

<template>
<router-view />
</template>

layout.vue

<template>
    <header></header>
    <main>
        <router-view />
    </main>
</template>

router的使用:

跳转页面:

import { useRouter } from "vue-router";

const router = useRouter()

router.push('/')

获取router

import { useRoute } from "vue-router";

const route = useRoute()

console.log(route.query)
console.log(route.matched)

vuex

安装

npm install vuex@next --save

配置store/index.js

import { createStore } from "vuex";

export default createStore({
  state() {
    return {
        user: {},
    };
  },
  mutations: {
    SAVE_USER: (state, user) => {
      state.user = user
    },
  },
  actions: {
      login({commit}, res) {
          commit('SAVE_USER', res.user)
      },
  }

挂载到main.js

import { createApp } from 'vue';
import App from './App.vue';
import store from './store';

const app = createApp(App)
app.use(store)
app.mount("#app")

使用

和在vue2中使用一致,没区别, vue3中据说推荐使用pinia

获取state参数

import store from "../store";

const user = store.state.user;

使用mutations

import store from "../store";

store.commit('SAVE_USER', user)

调用actions

import store from "../store";

store.dispatch("login");

Axios

Axiosvue3中使用和vue2无异


vue3使用echarts

安装

npm i echarts -S

使用

<template>
  <div id="histogramChart"></div>
</template>


<script setup>
import * as echarts from 'echarts'
import {onMounted, nextTick} from "vue";

    onMounted(() => { // 需要获取到element,所以是onMounted的Hook
      nextTick(() => {
        let myChart = echarts.init(document.getElementById("histogramChart"));
        myChart.setOption({
            legend: {},
          grid: {
            left: '1%',
            right: '13%',
            bottom: '3%',
            containLabel: true
          },
          tooltip: {},
          dataset: {
            source: [
              ['product', '中高风险车辆', '营运车辆', '危险品车辆'],
              ['周一', 43.3, 85.8, 93.7],
              ['周二', 83.1, 73.4, 55.1],
              ['周三', 86.4, 65.2, 82.5],
              ['周四', 66, 53.9, 80],
              ['周五', 72.4, 60, 39.1],
              ['周六', 55, 69, 39.1],
              ['周日', 74, 59, 38],
            ]
          },
          xAxis: { type: 'category' },
          yAxis: {},
          series: [{ type: 'bar' }, { type: 'bar' }, { type: 'bar' }]
        });
        window.onresize = function () { // 自适应大小
          myChart.resize();
        };
       })
</script>

响应式原理

Vue2-defineProperty

<script>
    // 源数据
    let person = {
        name: 'san',
        age: 18
    }
    // 模拟vue2 实现响应式
    let p = {}    // 先定义一个空对象
    // ‘name’:操作的属性名, 多个属性时循环添加defineProperty
    Object.defineProperty(p, 'name', {
        configgurable:true,
        get() {
            return person.name
        },
        set(value) {
            consoloe.log(`修改name属性`,to update page)
            person.name = value
        }
    })
</script>

Vue3-Proxy

<script>
    // 源数据
    let person = {
        name: 'san',
        age: 18
    }
    // 模拟vue3 实现响应式
    // new Proxy(代理的源数据, {监听操作:get, set, deleteProperty})
    const p = new Proxy(person, {
        // 读取p某个数据时
        get(target, propName) {
            console.log(`读取p的${propName}属性`)
            // return target[propName]
            return Reflect.get(target, propName)
        },
        // 修改 追加属性时候调用
        set(target, propName, value) {
            consoloe.log(`修改p的${propName}属性`,to update page)
            //target[propName] = value
            Reflect.set(target, propName, value)
        },
        // 删除p某个数据调用
        deleteProperty(target, propName) {
            console.log(`删除p的${propName}`,to update page)
            // return delete target[propName]
            return Reflect.deleteProperty(target, propName)
        }
    })
</script>

参考视频地址:

Proxy: https://www.bilibili.com/video/BV1Zy4y1K7SH?p=146

Reflect: https://www.bilibili.com/video/BV1Zy4y1K7SH?p=147


异步引入组件 与 Suspense

猜想:作用于 在数据未加载完时候,类似于骨架屏显示

<template>
<Suspense>
    <template v-slot:default>
        <Child />
    </template>
    <template v-slot:fallback>
        加载中,稍后
    </template>
</Suspense>
</template>

import { defineAsyncComponent }  from 'vue'

const Child = defineAsyncComponent(() => import('./components/chid.vue'))

teleport

猜想; 用于全局模态框类似情况, 将在嵌套子组件的html 传送到指定元素下显示

// to: 要传送的位置,支持 html, css, id选择器,【html, body, div, .css, #id】
<teleport to="html">
    // 模态框
</teleport>



才疏学浅,以上只是在搭建系统中遇到的,如有错误,还请赐教。

原文地址: https://blog.zhanghaoran.ren/article/html/vue3ChuBuShiYongBiJi.html

2022.2.21


2022.3.3 二次更新:依赖包版本、vite相关配置

2022.3.4 三次更新:vue响应式原理, vue3新增API:teleport,Suspense