文章目录
- 自定义创建项目
- ESlint 代码规范
- vuex 概述
- 创建仓库
- 向仓库提供数据
- 使用仓库中的数据
- 通过store直接访问
- 通过辅助函数 mapState(简化)
- mutations传参语法(同步
- 实时输入,实时更新
- 辅助函数 mapMutations
- action (异步
- 辅助函数mapActions
- getters (类似于计算属性
- 通过store访问getters
- 通过辅助函数mapGetters映射
- 模块module
- 使用模块中的数据 / 模块中state的访问语法
- 直接通过模块名访问
- 通过mapState映射
- 默认根级别的映射 ...mapState(['user', 'setting'])
- 子模块映射 mapState('模块名',['xxx]) +开启命名空间
- 使用模块中getters中的数据 / 模块中getters的访问语法
- 直接通过模块名访问 $store.getters['模块名/xxx']
- 通过mapGetters映射
- 默认根级别映射mapGetters(['xxx'])
- 子模块映射mapGetters('模块名',['xxx'])+开启命名空间Son2.vue
- 掌握模块中的mutation调用语法
- 直接通过store调用 $store.commit('模块名/xxx',额外参数)
- 通过mapMutations映射
- 默认根级别映射mapMutations(['xxx'])
- 子模块映射mapMutations('模块名',['xxx'])+开启命名空间
- 直接通过模块名访问 $store.dispatch('模块名/xxx',额外参数)
- 通过mapActions映射
- 默认根级别映射mapActions(['xxx'])
- 子模块映射mapActions('模块名',['xxx'])+开启命名空间
自定义创建项目
vue create exp-mobile(项目名
2.选第三个,自定义
3.空格是选中
4.选vue 2.x
5.选择哈希
6.选择Less处理器
7.选择无分号规范
8.选择保存时校验
9.将配置文件放在单独文件中
小结
ESlint 代码规范
vuex 概述
创建仓库
store/index.js
// 这里存放的就是vuex相关的核心代码
import Vue from 'vue'
import Vuex from 'vuex'
// 插件安装
Vue.use(Vuex)
// 创建空仓库
const store = new Vuex.Store()
// 导出给main.js
export default store
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store //! !!!!
// 仓库在所有组件都可以访问,用this.$store
}).$mount('#app')
App.vue
created () {
console.log(this.$store)
}
向仓库提供数据
store/index.js
// 创建空仓库
const store = new Vuex.Store({
// 通过state可以提供数据,所有组件共享的数据,任意组件都可以访问
state: {
title: 'hhhhh',
count: 100
}
})
使用仓库中的数据
通过store直接访问
components/Son2.vue
div class="box">
<h2>Son2 子组件</h2>
从vuex中获取的值:<label>{{$store.state.count}}</label>
<br />
<button>值 - 1</button>
</div>
通过辅助函数 mapState(简化)
mapState把store中的数据
自动映射到组件的计算属性computed中
computed: {
...mapState(['count', 'title'])
},
App.vue 节选
<template>
<div id="app">
<h1>根组件{{ $store.state.title }}</h1>
<!-- 3.用了 mapState ,就直接简写 -->
<h1>根组件{{ title }}</h1>
<input type="text">
<Son1></Son1>
<hr>
<Son2></Son2>
</div>
</template>
<script>
import Son1 from './components/Son1.vue'
import Son2 from './components/Son2.vue'
// 1.导入
import { mapState } from 'vuex'
console.log(mapState(['count', 'title']))
export default {
name: 'app',
// 2.展开运算符进行映射
computed: {
...mapState(['count', 'title'])
},
# 组件(间接)修改仓库数据 mutation
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
strict: true,
state: {
title: 'hhhhh',
count: 100
},
// 通过mutations可以提供修改数据的方法
mutations: {
// 所有mutations函数,第一个参数,都是state
addCount (state) {
state.count++
}
}
})
export default store
App.vue
<span @click="handleAdd">count</span> <input type="text">
methods: {
handleAdd () {
// 调用
this.$store.commit('addCount')
}
},
mutations传参语法(同步
提交参数只能有一个,如果有多个参数,包装成一个对象传递
实时输入,实时更新
不能用v-model,因为vuex是单向数据流
但是v-model 等于 :value @input
App.vue
<input :value="title" @input="handleInput" type="text">
handleInput (e) {
// 1.实时获取输入框的值
console.log(e.target.value)
// 2.提交mutation,调用mutation函数
this.$store.commit('changeTitle', e.target.value)
}
store/index.js
changeTitle (state, newTitle) {
state.title = newTitle
}
辅助函数 mapMutations
把位于mutations中的方法
提取出来,映射到methods中
store/index.js
const store = new Vuex.Store({
strict: true,
state: {
title: 'hhhhh',
count: 100
},
// 通过mutations可以提供修改数据的方法
mutations: {
subCount (state, n) {
state.count -= n
},
changeTitle (state, newTitle) {
state.title = newTitle
},
changeCount (state, tt) {
state.count = tt
}
}
})
Son1.vue
<button @click="handleSub(10)">值 - 10</button>
<button @click="handleSub(20)">值 - 20</button>
<button @click="handleSub(30)">值 - 30</button>
<!-- 更简单的写法,连外面的函数都不套了 -->
<button @click="subCount(2)">值 - 2</button>
<br>
<button @click="changeTitle('qqq')">改成【qqq】标题</button>
...mapMutations(['subCount', 'changeTitle']),
handleSub (tt) {
this.subCount(tt)
},
action (异步
辅助函数mapActions
把actions中的方法
提取出来,映射到组件methods
中
( …mapMutations([‘subCount’, ‘changeTitle’]),和 …mapActions([‘changeCountAction’]) 都在methods中
index.js
// action 处理异步
// 不能直接操作state,操作state还是需要commit mutation
actions: {
// 此处未分模块,可当成store仓库
// context.commit('mutation名字',额外参数)
changeCountAction (context, num) {
// 这里是setTime模拟异步,以后大部分场景是发请求
setTimeout(() => {
context.commit('changeCount', num)
}, 2000)
}
}
Son2.vue
<button @click="changeCountAction(0)">2秒后改成count=0</button>
methods: {
changeTitle () {
this.$store.commit('changeTitle', 'sssss')
},
...mapActions(['changeCountAction']) // !!!!
}
getters (类似于计算属性
通过store访问getters
store/index.js
state: {
title: 'hhhhh',
count: 100,
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
},
// 类似于计算属性
getters: {
// 注意点:
// 1. 形参第一个参数,就是state
// 2. 必须有返回值,返回值就是getters的值
filterList (state) {
return state.list.filter(item => item > 5)
}
}
Son1.vue
<hr>
<div>{{$store.state.list}}</div>
<div>{{ $store.getters.filterList }}</div>
通过辅助函数mapGetters映射
Son2.vue
<hr>
<div>{{ filterList }}</div>
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['filterList'])
},
模块module
store/modules/user.js
const state = {
userInfo: {
name: 'slx',
age: 18
},
score: 80
}
const mutations = {}
const actions = {}
const getters = {}
export default {
state,
mutations,
actions,
getters
}
store/modules/setting.js
const state = {
theme: 'light'
}
const mutations = {}
const actions = {}
const getters = {}
export default {
state,
mutations,
actions,
getters
}
store/index.js
import setting from './modules/setting'
modules: {
user, setting
}
使用模块中的数据 / 模块中state的访问语法
子模块的状态,还是会挂到根级别的state中,属性名就是模块名
直接通过模块名访问
Son1.js
<div>{{ $store.state.user.userInfo.name }}</div>
通过mapState映射
默认根级别的映射 …mapState([‘user’, ‘setting’])
Son2.js
<div>{{ user.userInfo.name }}</div>
<div>{{ setting.theme }}</div>
import { mapState } from 'vuex'
computed: {
...mapState(['user', 'setting']),
},
子模块映射 mapState(‘模块名’,['xxx]) +开启命名空间
user.js
export default {
namespaced: true,//开启命名空间
state,
mutations,
actions,
getters
}
Son2.vue
<div>{{ userInfo.name }}</div>
<div>{{ score }}</div>
...mapState('user', ['userInfo', 'score']), //! !!!
使用模块中getters中的数据 / 模块中getters的访问语法
直接通过模块名访问 $store.getters[‘模块名/xxx’]
user.js
const getters = {
// 分模块后,state就是子模块的state
UpperName (state) {
return state.userInfo.name.toUpperCase()
}
}
Son1.vue
<div>{{ $store.getters['user/UpperName'] }}</div>
通过mapGetters映射
默认根级别映射mapGetters([‘xxx’])
Son2.vue
<div>{{ filterList }}</div>
...mapGetters(['filterList'])
store/index.js
getters: {
// 注意点:
// 1. 形参第一个参数,就是state
// 2. 必须有返回值,返回值就是getters的值
filterList (state) {
return state.list.filter(item => item > 5)
}
},
子模块映射mapGetters(‘模块名’,[‘xxx’])+开启命名空间Son2.vue
<div>{{ UpperName }}</div>
...mapGetters('user', ['UpperName']), //! !!!
掌握模块中的mutation调用语法
直接通过store调用 $store.commit(‘模块名/xxx’,额外参数)
setting.js
const mutations = {
setTheme (state, newtheme) {
state.theme = newtheme
}
}
export default {
namespaced: true,
state,
mutations,
actions,
getters
}
Son1.vue
<div>{{ $store.state.setting.theme }}</div>
<button @click="changeTheme">改主题色</button>
changeTheme () {
this.$store.commit('setting/setTheme', 'dark')
},
通过mapMutations映射
默认根级别映射mapMutations([‘xxx’])
子模块映射mapMutations(‘模块名’,[‘xxx’])+开启命名空间
setting.js
const state = {
theme: 'light',
size: 16
}
const mutations = {
setTheme (state, newtheme) {
state.theme = newtheme
},
setSize (state, newSize) {
state.size = newSize
}
}
Son2.vue
<div>{{$store.state.setting.size}}px</div>
<button @click="setSize(90)">改px</button>
//真的注意,放在methods里,不是computed
methods: {
...mapMutations('setting', ['setSize']),
...mapMutations('setting', ['setTheme'])
}
## 模块中action的访问语法 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ae6beb82840640eab8df3c6d8d540061.png)
直接通过模块名访问 $store.dispatch(‘模块名/xxx’,额外参数)
Son1.vue
<button @click="updateTheme2">一秒后更新</button>
methods: {
updateTheme2 () {
this.$store.dispatch('setting/setThemeSecond', 'orange')
},
setting.js
const actions = {
setThemeSecond (context, newTheme) {
setTimeout(() => {
// 调用mutation context上下文,默认提交的就是自己模块action和mutation
context.commit('setTheme', newTheme)
}, 1000)
}
}
通过mapActions映射
默认根级别映射mapActions([‘xxx’])
子模块映射mapActions(‘模块名’,[‘xxx’])+开启命名空间
Son2.vue
<button @click="setThemeSecond('black')">一秒后更新主题</button>
methods: {
...mapActions('setting', ['setThemeSecond'])
}