vue3项目搭建笔记

1,080 阅读4分钟

项目搭建

  • 使用vue-cli搭建项目,选择vue3相关的配置
  • 引入一些基本的插件vuexvue-routeraxios,ui方面我们选择使用element-plus
  • 配置方面根目录下创建vue.config.js文件,参考官方文档vue.config配置
  • 修改main.ts引入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'

createApp(App).use(store).use(router).use(ElementPlus).mount('#app')

基础知识

setup

  • vue3中保留vue2中的几乎所有组件属性,比如data,created,methods等
  • 新增了setup属性,执行时机位于beforeCreate和created之间,没有this,故使用时无法和vue2的data、methods串联
  • setup传入一个函数,你可以return一些参数供页面使用
  • setup中也可以使用生命周期函数,如onMounted, onUpdated, onUnmounted等
import { onMounted } from 'vue'
// ...
setup () {
    onMounted(() => {
      console.log('页面第一次加载完成后执行')
    })
}

reactive和ref、shallowReactive和shallowRef - 响应式数据

用于创建状态值

其中reactive用于创建普通对象、数组、或其它自定义对象,注意无法创建基础类型状态,并且创建其它类型状态时必须直接赋值才能使页面更新(比如Date)

ref一般用于创建基础类型、dom的ref

创建const r = ref(a)其实相当于创建const r = reactive({value: a}),故内部调用时要使用r.value

reactive和ref都是创建深响应式数据对象,即修改深层次的数据也可更新页面视图

<template>
	<div>
    	<div>{{num}}</div>
    	<div>{{state}}</div>
    	<div ref="divRef" />
    	<el-button @click="change">点击</el-button>
    </div>
</template>
import { reactive, ref } from 'vue'
// ...
setup () {
    const num = ref(0)
    const divRef = ref(null)
    const state = reactive({
      name: '张三',
      age: 12,
      orgIds: ['1', '2']
    })
    function change () {
      num.value += 1
      state.name = '李四'
      state.age = 14
      state.orgIds[0] = '3' // 单独执行也可使页面更新
      console.log(divRef.value)
      console.log(num.value)
      console.log(state.name)
    }
    return { num, divRef, state, change }
}

运行上面代码点击按钮可以看到数据发生了变化并且页面也刷新了

shallowReactive和shallowRef同上,只不过改成了创建浅响应式数据对象,即上面代码state.orgIds[0] = '3'不会导致界面更新

watchEffect、watch - 侦听器

  • 用于侦听数据,当侦听的部分数据被修改时,执行部分方法,返回一个停止侦听的方法

  • watchEffect和watch的区别是:

1、watch在创建时不执行,只有在侦听的状态修改时才执行,而watchEffect则会马上执行一次

2、watch第一个参数需要传入侦听的对象或者一个返回侦听对象的函数,watchEffect不需要

<template>
  <div>
    <h1>watch - 侦听器</h1>
    <p>count1: {{data.count1}}</p>
    <p>count2: {{data.count2}}</p>
    <button @click="stopAll">Stop All</button>
  </div>
</template>

import { reactive, watch } from "vue"
setup() {
    const data = reactive({ count1: 0, count2: 0 })
    const stop = watchEffect(() => console.log(`侦听器:${data.count}`))
    // 侦听单个数据源
    const stop1 = watch(data, () =>
      console.log("watch1", data.count1, data.count2)
    )
    // 侦听多个数据源
    const stop2 = watch([data.count1, data.count2], (now, bef) => {
      console.log(now, bef) // now表示当前状态,bef表示上一个状态
      console.log("watch2", data.count1, data.count2)
    })
    setInterval(() => {
      data.count1++
    }, 1000)
    return {
      data,
      stopAll: () => {
        stop()
        stop1()
        stop2()
      }
    }
  }

注意观察侦听的值

vuex 4

  • state状态
state: {
    count: 0
},

mutations修改状态(必须同步)

mutations: {
    increment (state, payload) {
      console.log(payload)
      state.count++
    }
},
  • actions可以写异步方法,不能直接修改状态值,必须通过mutations才能修改,使用场景,可以在这里编写接口查询,然后把查询数据存入store中
actions: {
  incrementAsync ({ commit }, { payload }) {
  	console.log(payload)
    setTimeout(() => {
      commit('increment', 'payload')
    }, 1000)
  }
}
  • getters类似计算属性
getters: {
	getCount (state) {
    	return state.count
    }
}

页面使用

import { useStore } from 'vuex'
// ...
setup () {
	const store = useStore() // 该方法不一定要在setup内使用
    // 通过store.commit('increment', 'payload')直接调用mutations的方法
    // 通过store.gettersgetCount直接获取getters方法的返回值
    // 通过store.dispatch('incrementAsync', 'payload')调用actions的方法
}
  • modules模块化管理状态 store文件夹下创建moduleA.ts文件
// store/index.ts
import { createStore } from 'vuex'
import moduleA from './moduleA'

export default createStore({
  // ...
  modules: {
    moduleA // 模块名为moduleA
  },
})
// store/moduleA.ts
import { Module } from 'vuex'

const moduleA: Module<{countA: number}, any> = {
  namespaced: true, // 设置为true使其成为带命名空间的模块
  state: {
    countA: 0
  },
  mutations: {
    increment (state, payload) {
      console.log(payload, state)
      state.countA++
    }
  },
  getters: {
    getCountA (state) {
      return state.countA
    }
  },
  modules: {}
}
export default moduleA

那么在页面上使用则改为

store.state.moduleA.countA
store.commit('moduleA/increment', 'hhh')

moduleA下也可再创建modules,若创建moduleAA则

store.commit('moduleA/moduleAA/increment', 'hhh')
// 直到最后一个斜杠前面都是命名空间,最后一个斜杠后为该空间下面的状态或方法
  • 注意:store.state状态改变后页面没有刷新,使用computed
const count = computed(() => store.state.count)

vue-router 4

import { useRoute, useRouter } from 'vue-router'
const route = useRoute() // 当前界面路由信息
const router = useRouter() // 界面跳转的一些方法

router中还包含addRoute、removeRoute等方法,可用于做动态路由或路由权限控制

参考资料