配置环境的最后一环。
配置UI
这里选用了Element Plus,忽略掉项目样式的设计时间。用现成的。
Element Plus,一套为开发者、设计师和产品经理准备的基于 Vue 3.0 的桌面端组件库。官方文档=>Elment Plus
使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用。
npm install element-plus --save //npm 配置 淘宝源,下载效果更佳,百度教程
// -s 安装。项目必须包。
进入入口文件main.js 引入它
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 路由
import store from './store' // vuex
// element 组件这里全部引入,也可定制按需引入,如只要button、table等用到的组件
import ElementPlus from 'element-plus'
// 所有组件相关的样式
import 'element-plus/lib/theme-chalk/index.css'
// 挂载
createApp(App).use(store).use(router).use(ElementPlus).mount('#app')
配置vue-router
这三个文件是启动时暂时的页面相关文件,也可以不删。留着。
App.vue去掉注释部分
<template>
<!-- <div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div> -->
<router-view />
</template>
<style>
然后创建view/home/index.vue
<template>
<el-row>
<el-col>欢迎来到漂流城!</el-col>
</el-row>
</template>
<script>
export default {
name: 'Home'
}
</script>
进到router/index.js
import { createRouter, createWebHistory } from 'vue-router'
/**
具体参数可以百度官方网查看
*/
const routes = [
{
path: '/', // localhost:7779 获取 home/inde.vue页面
name: 'Home',
component: () => import('@/views/home/index')
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
npm run serve //项目跑起来
vue-router的作用展示结束
配置Vuex
vuex管理项目的一些状态(类似全局变量)
官方文档:Vuex
进入store/index.js 查看vuex的基本构成
import { createStore } from 'vuex'
export default createStore({
state: {
// 状态变量
},
mutations: {
// 状态更改的地方
// 这里只能进行同步代码
},
actions: {
// 异步操作mutations (变相让mutation支持异步)
},
modules: {
// vuex 模块化
}
})
以下展示Vuex4的一些用法。会的可以忽略
State
State对象就包含了项目全部状态(未分模块)
使用:
//在state 定义一个状态(可以理解为项目全局变量)
state: {
// 状态变量
name: '麦克斯'
}
// home/index.vue
<template>
<el-row>
<el-col>{{ name}},欢迎来到漂流城!</el-col>
</el-row>
</template>
// 以下 是 三种 获取 state 调用,结果都一样
<script>
export default {
name: 'Home',
data() {
return {
name: this.$store.state.name // 定义一个变量来获取状态,名字随意
}
},
}
</script>
<script>
//computed监听
export default {
name: 'Home',
computed: {
name() {
return this.$store.state.name
}
}
}
</script>
<script>
//也可以引入辅助函数mapState 辅助函数,更方便管理状态
import { mapState } from 'vuex'
export default {
name: 'Home',
//computed: mapState({
// name: state => state.name
//}) // 这里是传对象
//computed: mapState([
//'name'
//]) // 这里是传数组,'name' 会被映射为state => state.name
computed: {
...mapState([
'name'
]) // 用一个工具函数将多个对象合并为一个
}
}
</script>
ctrl+c 保存index.vue。在回到网页看看结果
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
进入store/index.js 添加
state: {
// 状态变量
name: '麦克斯',
count: 0
},
mutations: {
// 状态更改的地方
// 这里只能进行同步代码
ADD(state) {
state.count++
},
// 支持带参数
ADDS(state, num) {
state.count += num
}
},
调用的2个方式,跟state类似
<template>
<el-row>
<el-col>{{ name }},欢迎来到漂流城!</el-col>
<el-col>{{ count }}</el-col>
<el-button @click="ADD">count+1</el-button>
<el-button @click="ADDS(10)">count+10</el-button>
<el-button @click="ADDSS()">count+1</el-button>
</el-row>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'Home',
computed: {
...mapState([
'name',
'count'
])
},
// 第一种
methods: {
add() {
this.$store.commit('ADD')
this.$store.commit('ADDS', 10)
}
}
// 第二种
methods: {
...mapMutations([
'ADD', // 将 `this.ADD()` 映射为 `this.$store.commit('ADD')`
// `mapMutations` 也支持传参:
'ADDS' // 将 `this.ADDS(amount)` 映射为 `this.$store.commit('ADDS', amount)`
]),
...mapMutations({ //自定义名称
ADDSS: 'ADD' // 将 `this.addss()` 映射为 `this.$store.commit('ADD')`
})
}
}
</script>
Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
进入 store/inde.js 加入以下代码
actions: {
// 异步操作mutations (变相让mutation支持异步)
add (context) {
context.commit('ADD')
}
},
// context 具有 store的属性 ,context.commit 提交一个 mutation,
//或者通过 context.state 和 context.getters 来获取 state 和 getters。
//利用结构写法,简化
actions: {
// 异步操作mutations (变相让mutation支持异步)
// 可以和 mutation 同名,
add({ commit }) {
commit('ADD')
}
// 带参数(一般为对象,可带参数更多)
adds({ commit }, data) {
commit('ADDS', data.num)
}
},
允许异步
actions: {
add({ commit }) {
setTimeout(() => {
commit('ADD')
}, 1000)
}
}
页面调用Action
store.dispatch('add')
// 带参数(一般为对象)
store.dispatch('adds', {
amount: 10
})
<template>
<el-row>
<el-col>{{ name }},欢迎来到漂流城!</el-col>
<el-col>{{ count }}</el-col>
<el-button @click="ADD">count+1</el-button>
<el-button @click="ADDS(10)">count+10</el-button>
<el-button @click="ADDSS">count+1</el-button>
<el-col>Action:</el-col>
<el-button @click="add">add</el-button>
<el-button @click="adds({ num: 10 })">adds(10)</el-button>
<el-button @click="addss">addss+1</el-button>
</el-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
name: 'Home',
computed: {
...mapState([
'name',
'count'
])
},
// methods: {
// add() {
// this.$store.commit('ADD')
// }
// }
methods: {
...mapMutations([
'ADD', // 将 `this.ADD()` 映射为 `this.$store.commit('ADD')`
// `mapMutations` 支持带参数
'ADDS' // 将 `this.ADDS(amount)` 映射为 `this.$store.commit('ADDS', amount)`
]),
...mapMutations({
ADDSS: 'ADD' // 将 `this.ADDSS()` 映射为 `this.$store.commit('ADD')`
}),
...mapActions([
'add', // map `this.add()` to `this.$store.dispatch('add')`
// `mapActions` 待参数
'adds' // map `this.adds(amount)` 映射为 `this.$store.dispatch('adds', amount)`
]),
...mapActions({
addss: 'ADD' // map `this.addss()` 映射为 `this.$store.dispatch('add')`
})
}
}
</script>
以上就是vuex 简单调用,实际上根据项目的需求,状态也会随之变多,维护起来也是挺头疼的。
为了解决这个问题,Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = createStore({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> `moduleA`'s state
store.state.b // -> `moduleB`'s state
模块化的使用例子:
进入 store/index.js。删除之前的所有内容,也可以保存方便 复习
import { createStore } from 'vuex'
const dog = {
namespaced: true, // 需要开启命名空间 识别这个module
state: () => ({
name: '麦克斯',
sex: '6'
}),
mutations: {},
actions: {}
}
export default createStore({
modules: {
dog // es6语法 === dog:dog 同名可以简写
}
})
state状态的获取
进入home/index.vue,删除之前的内容
<template>
<el-row>
<el-col>----信息----</el-col>
<el-col>name2: {{ name2 }}</el-col>
<el-col>年龄2: {{ sex2 }}</el-col>
<el-col>name1: {{ name1 }}</el-col>
<el-col>年龄: {{ sex }}</el-col>
</el-row>
</template>
<script>
import { mapState } from 'vuex'
// 模块化的调用
export default {
name: 'Home',
data() {
return {
// 第一种方式获取
name1: this.$store.state.dog.name
}
},
computed: {
// 第二种方式获取 对象
...mapState({
name2: state => state.dog.name
}),
// 第三种方式获取 对象
...mapState('dog', {
sex2: state => state.sex
}),
// 第四种 方式, 数组
...mapState('dog', [
'sex'
])
}
}
</script>
</script>
mutations的调用
store/index.js 加入
...
mutations: {
CHANGE_NAME(state) {
state.name = '旺财'
},
CHANGE_SEX(state, num) {
state.sex = num
}
},
...
home/index.vue 加入
//teamplate
<el-col>--- Mutations ---</el-col>
<el-col><el-button @click="change">Change()</el-button></el-col>
<el-col><el-button @click="CHANGE_NAME">CHANGE_NAME()</el-button></el-col>
<el-col><el-button @click="CHANGE_SEX(10)">CHANGE_SEX(10)</el-button></el-col>
<el-col><el-button @click="change2">change2()</el-button></el-col>
// script
methods: {
// 第一种
change() {
this.$store.commit('dog/CHANGE_NAME')
},
// 第二种
...mapMutations('dog', [
'CHANGE_NAME', // 将 `this.CHANGE_NAME()` 映射为 `this.$store.commit('dog/CHANGE_NAME')`
// `mapMutations` 也支持传参:
'CHANGE_SEX' // 将 `this.CHANGE_SEX(amount)` 映射为 `this.$store.commit('dog/CHANGE_SEX', amount)`
]),
// 第三种
...mapMutations('dog', { // 自定义名称
change2: 'CHANGE_NAME' // 将 `this.change2()` 映射为 `this.$store.commit('dog/CHANGE_NAME')`
})
}
action 的模块化后的调用
store/index.js 加入
actions: {
changeName({ commit }) {
commit('CHANGE_NAME')
},
changeSex({ commit }, data) {
commit(' CHANGE_SEX', data.num) // 通常传入一个对象,方便传递更多参数
}
}
login/index.vue加入
//teamplate
<el-col>--- Action ---</el-col>
<el-col><el-button @click="change3">Change()</el-button></el-col>
<el-col><el-button @click="changeName">changeName</el-button></el-col>
<el-col><el-button @click="changeSex({num: 10})">changeSex({num: 10})</el-button></el-col>
<el-col><el-button @click="change4">change4()</el-button></el-col>
//script
methods: {
// 第一种
change3() {
this.$store.dispatch('dog/changeName')
this.$store.dispatch('dog/changeSex', { num: 10 })
},
// 第二种
...mapActions('dog', [
'changeName',
'changeSex'
]),
// 第三种,自定义方法
...mapActions('dog', {
change4: 'changeName'
})
}
getters
有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
store/index.js 加入getters
...state{
speark: '旺旺' //加入一个新的状态
}
...mutations
...actions
getters: {
// speark: state => state.speark,
speark: state => {
//这里可以对状态进行一些操作,如数组过滤等.
return state.speark
}
}
getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值:
// 对应getter 对象里的属性。可以和state里的同名方便记
store.getters.name// -> [{name: '麦克斯'...}]
home/index.vue 使用getters
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters('dog', [ // 直接映射
'speark' // this.speark 会被映射为store.getters.speark
]),
...mapGetters('dog', { // 自定义变量
speark1: 'speark' // this.speark1 会被映射为store.getters.speark
})
}
//由于模块化了。所以加入了模块写法。
好了,到这来 Vuex 的普遍用法介绍完了。更深的高级写法可以去看官网学习。
这里的状态是响应式的。不管在那个模板变动了这些状态。相关视图都会 更新。
项目结构的Vuex 配置
这里配置项目的Vuex 结构。以上联系的文件可以保留。方便回忆。
目录结构
src/store/index.js、
src/store/getters.js、
src/store/modules/app.js、
app.js 某个模块
const state = {
name: 'dky后台'
}
const mutations = {}
const actions = {}
export default {
namespaced: true,
state,
mutations,
actions
}
整体getters
getters.js
const getters = {
name: state => state.app.name,
}
export default getters
index.js
import { createStore } from 'vuex'
import getters from './getters'
// webpack Api 它会遍历文件夹中的指定文件,然后自动导入,不用都import
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './app.js' => 'app' $1 即 app
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = createStore({
modules,
getters
})
export default store
至此,模块化配置结束。有新的模块直接在module问价夹创建 moduleName.js 定义模块内 state,mutations,action 即可。调用和之前一样