VueDemo

编程入门 行业动态 更新时间:2024-10-14 04:28:04

VueDemo

VueDemo

14.状态管理器

 

Vuex 是什么? | Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

状态传值

  • 父组件给子组件传值

  • 子组件给父组件传值

  • 非父子组件(兄弟组件)传值

  • 子组件直接使用父组件的数据和方法

  • 父组件直接使用子组件的数据和方法

  • 跨组件传值

  • 状态管理器

  • 多个视图依赖于同一状态。

  • 来自不同视图的行为需要变更同一状态。

 

14.0 构建首页的头部组件

<template><div class="box"><header class="header"><ul><li>北京</li><li>搜索框</li><li v-if="true">登录</li><li v-else>我的</li></ul></header><div class="content" ref="content">....</div>  </div>
</template>
<script>
.....
</script>
​
<style lang='stylus' scoped>
// scoped 代表该样式只在当前组件是有效的,不会影响其他组件的样式
....
.headerulheight 100%display flexliflex 1
</style>
​

14.1 第一版登录状态

异步操作在组件,组件中直接提交mutations

定义状态管理器

// src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
​
Vue.use(Vuex)
​
export default new Vuex.Store({state: {// ? 为什么要从本地存储设置 状态管理器的初始值// 因为每次刷新页面都会使 状态管理器 重置loginState: localStorage.getItem('loginState') === 'true'},mutations: {changeLoginState (state, payload) { // state 所有的状态  payload 参数state.loginState = payload}},actions: {},modules: {}
})
​

登录时保存状态

// 修改状态管理器中的代码 --- 代码不要看图,只看图中的代码位置,实际代码替换如下
this.$storemit('changeLoginState', true)

底部组件获取登录状态

<template><!-- div.container>div.box>header.header+div.content --><div class="container"><router-view></router-view><footer class="footer" v-if="!$route.meta.hidden"><ul><router-link to="/home" tag="li"><span class="iconfont icon-shouye"></span><p>首页</p></router-link><router-link to="/kind" tag="li"><span class="iconfont icon-fenlei"></span><p>分类</p></router-link><router-link to="/cart" tag="li"><span class="iconfont icon-gouwuche"></span><p>购物车</p></router-link><router-link v-if="loginState" to="/user" tag="li"><span class="iconfont icon-My"></span><p>我的</p></router-link><router-link v-else to="/login" tag="li"><span class="iconfont icon-My"></span><p>未登录</p></router-link></ul></footer><div class="tip">请将屏幕竖向浏览</div></div>
</template>
<script>
export default {// 使用计算属性获取状态管理器中的状态computed: {loginState () {return this.$store.state.loginState}}
}
</script>
​
<style lang="stylus">
....
</style>
​
// src/views/home/index.vue
<template><div class="box"><header class="header"><ul><li>北京</li><li>搜索框</li><router-link tag="li" to="/user" v-if="loginState">我的</router-link><router-link tag="li" to="/login" v-else>登录</router-link></ul></header><div class="content" ref="content">....</div>  </div>
</template>
<script>
export default {computed: {loginState () {return this.$store.state.loginState}},....
}
</script>
​
<style lang='stylus' scoped>
// scoped 代表该样式只在当前组件是有效的,不会影响其他组件的样式
....
.headerulheight 100%display flexliflex 1
</style>
​
​

退出登录

<template><div class="box"><header class="header">user header</header><div class="content">
​<button v-if="loginState" @click="logout">退出</button><button v-else @click="login"> 登录</button></div></div>
</template>
<script>
export default {computed: {loginState () {return this.$store.state.loginState}},methods: {logout () {localStorage.removeItem('token')localStorage.removeItem('userid')localStorage.removeItem('loginState')this.$storemit('changeLoginState', false) // 二次渲染的关键this.$router.push('/login')},login () {this.$router.push('/login')}}
}
</script>
​

总结:登录时,异步的登录操作放到了 登录组件中

14.2 第二版登录状态

登录时,异步的登录操作放到了 状态管理器中,通过组件触发状态管理器执行 异步操作

登录的代码拷贝到了 store/index.js中的actions内

import Vue from 'vue'
import Vuex from 'vuex'
import router from '../router'
import { Dialog, Toast } from 'vant'
import { login } from './../api/user'
Vue.use(Vuex)
​
export default new Vuex.Store({state: {// ? 为什么要从本地存储设置 状态管理器的初始值// 因为每次刷新页面都会使 状态管理器 重置loginState: localStorage.getItem('loginState') === 'true'},mutations: {changeLoginState (state, payload) { // state 所有的状态  payload 参数state.loginState = payload}},actions: {// context 上下文对象 ---  store// params 参数loginAction (context, parmas) {login({loginname: parmas.loginname,password: parmas.password}).then(res => {if (res.data.code === '10010') {// 账户不存在,提醒用户是否要立即注册Dialog.confirm({message: '该用户还未注册,是否立即注册',confirmButtonText: '立即注册',confirmButtonColor: '#ff6666',cancelButtonText: '取消',cancelButtonColor: '#999'}).then(() => {router.push('/register/step1')}).catch(() => {// on cancel})} else if (res.data.code === '10011') {// 提醒用户密码错误, 视情况而定是否需要清空密码输入框 this.password = ''Toast('密码错误')} else {// 登录成功Toast('登录成功')localStorage.setItem('userid', res.data.data.userid) // 知道是谁localStorage.setItem('token', res.data.data.token) // 后端验证用户的登录状态localStorage.setItem('loginState', true) // 前端自检登录状态
​// 使用状态管理器修改状态contextmit('changeLoginState', true) // 修改状态管理器中的loginState的值为true// 返回上一页router.back()}})}},modules: {}
})
​
<template><div class="box"><header class="header"><van-nav-bartitle="嗨购登录"left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="form" v-if="type === '1'"><van-field v-model="loginname" placeholder="用户名/手机号/邮箱" clearable/><van-field v-model="password" type="password" placeholder="请输入密码" clearable/><p class="passwordTip" v-if="passwordTipFlag">输入至少6位,包含至少一个大写字母,1个小写字母,1个数字</p><div class="my-button"><van-button color="#ff6666" :disabled="adminameFlag"  block round @click="adminameLoginFn">登录</van-button></div></div><div class="form" v-if="type === '0'"><van-field v-model="tel" type="tel" placeholder="手机号码" clearable/><van-fieldv-model="telcode"centerclearableplaceholder="请输入短信验证码"><template #button><van-button size="small" >发送短信验证码</van-button></template></van-field><div class="my-button"><van-button color="#ff6666"  block round>登录</van-button></div></div><!-- 登录方式以及 注册提示 --><ul class="more"><li @click="changeType"><span v-if="type === '1'">短信验证码登录</span><span v-else>账号密码登录</span></li><router-link to="/register/step1" tag="li">手机快速注册</router-link></ul><div class="my-divider"><van-divider>其他登录方式</van-divider></div><div class="my-login-type"><van-row type="flex" justify="center"><van-col span="6"><van-image :src="qq" width="48" height="48"/><p>QQ</p></van-col><van-col span="6"><van-image :src="wx" width="48" height="48"/><p>微信</p></van-col><van-col span="6"><van-image :src="apple" width="48" height="48"/><p>苹果</p></van-col></van-row></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Field, Button, Divider, Col, Row, Image as VanImage } from 'vant'
​
Vue.use(NavBar)
Vue.use(Field)
Vue.use(Button)
Vue.use(Divider)
Vue.use(Col)
Vue.use(Row)
Vue.use(VanImage)
export default {data () {return {qq: 'data:image/png;base64,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',wx: 'data:image/png;base64,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',apple: 'data:image/png;base64,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',tel: '',password: '',loginname: '',telcode: '',type: '1' // 1表示账户名密码 0表示手机验证码}},computed: {adminameFlag () {if (this.loginname !== '' && /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/.test(this.password)) {return false} else {return true}},passwordTipFlag () {if (this.password === '' || /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/.test(this.password)) {return false} else {return true}}},methods: {changeType () {this.type = this.type === '1' ? '0' : '1'},adminameLoginFn () {console.log('1111111')// 异步操作this.$store.dispatch('loginAction', {loginname: this.loginname,password: this.password})}}
}
</script>
​
<style lang="stylus">
.container .box .contentpadding 30px 15pxbackground-color #ffffff
​
.form.my-buttonmargin-top 30px
.moremargin-top 20pxdisplay flexliflex 1&:nth-child(1)text-align left&:nth-child(2)text-align right
.my-dividermargin-top 80px
.passwordTipcolor #f66font-size 12px
</style>
​

异步操作在组件,组件中通过

this.$storemit()改变数据

异步操作在状态管理器,组件中通过

this.$store.dispatch() 触发,通过其内部的 contextmit() 改变数据

组件中通过this.$store.state获取状态,可以配合计算属性使用

14.3 使用辅助函数mapState获取状态

之前的案例是 通过 计算属性 计算得到 状态,通过 this.$store.state获取得到

mapState的是一个对象或者数组

// App.vue

<template><!-- div.container>div.box>header.header+div.content --><div class="container"><!-- <div class="box"><header class="header">header</header><div class="content">content</div></div> --><router-view></router-view><footer class="footer" v-if="!$route.meta.hidden"><ul><router-link to="/home" tag="li"><span class="iconfont icon-shouye"></span><p>首页</p></router-link><router-link to="/kind" tag="li"><span class="iconfont icon-fenlei"></span><p>分类</p></router-link><router-link to="/cart" tag="li"><span class="iconfont icon-gouwuche"></span><p>购物车</p></router-link><router-link v-if="loginState" to="/user" tag="li"><span class="iconfont icon-My"></span><p>我的</p></router-link><router-link v-else to="/login" tag="li"><span class="iconfont icon-My"></span><p>未登录</p></router-link></ul></footer><div class="tip">请将屏幕竖向浏览</div></div>
</template>
<script>
import { mapState } from 'vuex'
export default {// 使用计算属性获取状态管理器中的状态computed: {// loginState () {//   return this.$store.state.loginState// }...mapState({loginState: state => state.loginState})}
}
</script>
​
<style lang="stylus">
...
</style>
​

// src/views/home/index.vue

<template><div class="box">....</div>
</template>
<script>
...
import { mapState } from 'vuex'
export default {computed: {// loginState () {//   return this.$store.state.loginState// }...mapState({loginState: state => state.loginState})},....
}
</script>
​
<style lang='stylus' scoped>
/...
</style>
​

// src/views/user/index.vue

<template><div class="box"><header class="header">user header</header><div class="content">
​<button v-if="loginState" @click="logout">退出</button><button v-else @click="login"> 登录</button></div></div>
</template>
<script>
import { mapState } from 'vuex'
export default {computed: {// loginState () {//   return this.$store.state.loginState// }...mapState({loginState: state => state.loginState})},methods: {logout () {localStorage.removeItem('token')localStorage.removeItem('userid')localStorage.removeItem('loginState')this.$storemit('changeLoginState', false) // 二次渲染的关键this.$router.push('/login')},login () {this.$router.push('/login')}}
}
</script>
​

14.4 使用辅助函数mapMutations 改变状态

这个辅助函数使用场景: 组件中去改变 mutation

// views/user/index.vue

<template><div class="box"><header class="header">user header</header><div class="content">
​<button v-if="loginState" @click="logout">退出</button><button v-else @click="login"> 登录</button></div></div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {computed: {// loginState () {//   return this.$store.state.loginState// }...mapState({loginState: state => state.loginState})},methods: {...mapMutations({changeLoginState: 'changeLoginState' // key随意 - 事件,value即为mutation中的值,一般情况下二者相同}),logout () {localStorage.removeItem('token')localStorage.removeItem('userid')localStorage.removeItem('loginState')// this.$storemit('changeLoginState', false) // 二次渲染的关键this.changeLoginState(false) // 事件中通过 this.key事件(参数)this.$router.push('/login')},login () {this.$router.push('/login')}}
}
</script>
​

14.5 使用辅助函数 mapActions 触发 acitons

组件触发 action,aciton提交mutation

// views/login/index.vue

<template><div class="box"><header class="header"><van-nav-bartitle="嗨购登录"left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="form" v-if="type === '1'"><van-field v-model="loginname" placeholder="用户名/手机号/邮箱" clearable/><van-field v-model="password" type="password" placeholder="请输入密码" clearable/><p class="passwordTip" v-if="passwordTipFlag">输入至少6位,包含至少一个大写字母,1个小写字母,1个数字</p><div class="my-button"><van-button color="#ff6666" :disabled="adminameFlag"  block round @click="adminameLoginFn">登录</van-button></div></div><div class="form" v-if="type === '0'"><van-field v-model="tel" type="tel" placeholder="手机号码" clearable/><van-fieldv-model="telcode"centerclearableplaceholder="请输入短信验证码"><template #button><van-button size="small" >发送短信验证码</van-button></template></van-field><div class="my-button"><van-button color="#ff6666"  block round>登录</van-button></div></div><!-- 登录方式以及 注册提示 --><ul class="more"><li @click="changeType"><span v-if="type === '1'">短信验证码登录</span><span v-else>账号密码登录</span></li><router-link to="/register/step1" tag="li">手机快速注册</router-link></ul><div class="my-divider"><van-divider>其他登录方式</van-divider></div><div class="my-login-type"><van-row type="flex" justify="center"><van-col span="6"><van-image :src="qq" width="48" height="48"/><p>QQ</p></van-col><van-col span="6"><van-image :src="wx" width="48" height="48"/><p>微信</p></van-col><van-col span="6"><van-image :src="apple" width="48" height="48"/><p>苹果</p></van-col></van-row></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Field, Button, Divider, Col, Row, Image as VanImage } from 'vant'
import { mapActions } from 'vuex'
Vue.use(NavBar)
Vue.use(Field)
Vue.use(Button)
Vue.use(Divider)
Vue.use(Col)
Vue.use(Row)
Vue.use(VanImage)
export default {data () {return {qq: 'data:image/png;base64,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',wx: 'data:image/png;base64,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',apple: 'data:image/png;base64,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',tel: '',password: '',loginname: '',telcode: '',type: '1' // 1表示账户名密码 0表示手机验证码}},computed: {adminameFlag () {if (this.loginname !== '' && /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/.test(this.password)) {return false} else {return true}},passwordTipFlag () {if (this.password === '' || /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/.test(this.password)) {return false} else {return true}}},methods: {...mapActions({loginAction: 'loginAction'}),changeType () {this.type = this.type === '1' ? '0' : '1'},adminameLoginFn () {console.log('1111111')// 异步操作// this.$store.dispatch('loginAction', {//   loginname: this.loginname,//   password: this.password// })this.loginAction({loginname: this.loginname,password: this.password})}}
}
</script>
​
<style lang="stylus">
.container .box .contentpadding 30px 15pxbackground-color #ffffff
​
.form.my-buttonmargin-top 30px
.moremargin-top 20pxdisplay flexliflex 1&:nth-child(1)text-align left&:nth-child(2)text-align right
.my-dividermargin-top 80px
.passwordTipcolor #f66font-size 12px
</style>
​

14.6 getters以及ma pGetters

// src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import router from '../router'
import { Dialog, Toast } from 'vant'
import { login } from './../api/user'
Vue.use(Vuex)
​
export default new Vuex.Store({state: {list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5],// ? 为什么要从本地存储设置 状态管理器的初始值// 因为每次刷新页面都会使 状态管理器 重置loginState: localStorage.getItem('loginState') === 'true'},getters: { // 可以看作是state的计算属性,类似于computedlen: state => state.list.length},mutations: {changeLoginState (state, payload) { // state 所有的状态  payload 参数state.loginState = payload}},actions: {// context 上下文对象 ---  store// params 参数loginAction (context, parmas) {login({loginname: parmas.loginname,password: parmas.password}).then(res => {if (res.data.code === '10010') {// 账户不存在,提醒用户是否要立即注册Dialog.confirm({message: '该用户还未注册,是否立即注册',confirmButtonText: '立即注册',confirmButtonColor: '#ff6666',cancelButtonText: '取消',cancelButtonColor: '#999'}).then(() => {router.push('/register/step1')}).catch(() => {// on cancel})} else if (res.data.code === '10011') {// 提醒用户密码错误, 视情况而定是否需要清空密码输入框 this.password = ''Toast('密码错误')} else {// 登录成功Toast('登录成功')localStorage.setItem('userid', res.data.data.userid) // 知道是谁localStorage.setItem('token', res.data.data.token) // 后端验证用户的登录状态localStorage.setItem('loginState', true) // 前端自检登录状态
​// 使用状态管理器修改状态contextmit('changeLoginState', true) // 修改状态管理器中的loginState的值为true// 返回上一页router.back()}})}},modules: {}
})
​

// src/views/user/index.vue

<template><div class="box"><header class="header">user header</header><div class="content">
​<button v-if="loginState" @click="logout">退出</button><button v-else @click="login"> 登录</button>{{ listLen }}</div></div>
</template>
<script>
import { mapState, mapMutations, mapGetters } from 'vuex'
export default {computed: {// loginState () {//   return this.$store.state.loginState// }...mapState({loginState: state => state.loginState}),// listLen () {//   return this.$store.getters.len// }...mapGetters({listLen: 'len'})},methods: {...mapMutations({changeLoginState: 'changeLoginState' // key随意 - 事件,value即为mutation中的值,一般情况下二者相同}),logout () {localStorage.removeItem('token')localStorage.removeItem('userid')localStorage.removeItem('loginState')// this.$storemit('changeLoginState', false) // 二次渲染的关键this.changeLoginState(false) // 事件中通过 this.key事件(参数)this.$router.push('/login')},login () {this.$router.push('/login')}}
}
</script>
​

15 分模块的状态管理器

便于团队的开发协作

vue的实例中 可以 使用 computed 计算属性

vuex 中可以 使用 getters 计算属性

15.1 构建用户的相关的模块

// store/modules/user.js
import router from '../../router'
import { Dialog, Toast } from 'vant'
import { login } from './../../api/user'
export default {namespaced: true, // 命名空间,作用很大,用来标识是哪一个模块state: {list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5],// ? 为什么要从本地存储设置 状态管理器的初始值// 因为每次刷新页面都会使 状态管理器 重置loginState: localStorage.getItem('loginState') === 'true'},
​mutations: {changeLoginState (state, payload) { // state 所有的状态  payload 参数state.loginState = payload}},actions: {// context 上下文对象 ---  store// params 参数loginAction (context, parmas) {login({loginname: parmas.loginname,password: parmas.password}).then(res => {if (res.data.code === '10010') {// 账户不存在,提醒用户是否要立即注册Dialog.confirm({message: '该用户还未注册,是否立即注册',confirmButtonText: '立即注册',confirmButtonColor: '#ff6666',cancelButtonText: '取消',cancelButtonColor: '#999'}).then(() => {router.push('/register/step1')}).catch(() => {// on cancel})} else if (res.data.code === '10011') {// 提醒用户密码错误, 视情况而定是否需要清空密码输入框 this.password = ''Toast('密码错误')} else {// 登录成功Toast('登录成功')localStorage.setItem('userid', res.data.data.userid) // 知道是谁localStorage.setItem('token', res.data.data.token) // 后端验证用户的登录状态localStorage.setItem('loginState', true) // 前端自检登录状态
​// 使用状态管理器修改状态contextmit('changeLoginState', true) // 修改状态管理器中的loginState的值为true// 返回上一页router.back()}})}}
}
​
​
​
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
​
export default new Vuex.Store({getters: { // 可以看作是state的计算属性,类似于computedlen: state => state.user.list.length},modules: { // 整合模块user}
})
​

Src/App.vue

<template><!-- div.container>div.box>header.header+div.content --><div class="container"><!-- <div class="box"><header class="header">header</header><div class="content">content</div></div> --><router-view></router-view><footer class="footer" v-if="!$route.meta.hidden"><ul><router-link to="/home" tag="li"><span class="iconfont icon-shouye"></span><p>首页</p></router-link><router-link to="/kind" tag="li"><span class="iconfont icon-fenlei"></span><p>分类</p></router-link><router-link to="/cart" tag="li"><span class="iconfont icon-gouwuche"></span><p>购物车</p></router-link><router-link v-if="loginState" to="/user" tag="li"><span class="iconfont icon-My"></span><p>我的</p></router-link><router-link v-else to="/login" tag="li"><span class="iconfont icon-My"></span><p>未登录</p></router-link></ul></footer><div class="tip">请将屏幕竖向浏览</div></div>
</template>
<script>
import { mapState } from 'vuex'
export default {// 使用计算属性获取状态管理器中的状态computed: {// loginState () {//   return this.$store.state.user.loginState// }...mapState({loginState: state => state.user.loginState})}
}
</script>
​
<style lang="stylus">
...
</style>
​

// src/views/home/index.vue

<template><div class="box">....
</template>
<script>
import Vue from 'vue'
import { Swipe, SwipeItem, Grid, GridItem, Image as VanImage, CountDown, Icon, List, PullRefresh } from 'vant'
import { getBannerList, getSeckillList, getProList } from '@/api/home' // @ 代表的就是src的目录
import ProList from '@/components/ProList'
import { mapState } from 'vuex'
Vue.use(Swipe)
Vue.use(SwipeItem)
Vue.use(Grid)
Vue.use(GridItem)
Vue.use(VanImage)
Vue.use(CountDown)
Vue.use(Icon)
Vue.use(List)
Vue.use(PullRefresh)
export default {computed: {// loginState () {//   return this.$store.state.loginState// }...mapState({loginState: state => state.user.loginState})},....
}
</script>
​
<style lang='stylus' scoped>
....
</style>
​

15.2 状态管理器中使用模块

15.3 登录时改变状态

Src/views/login/index.vue

<template><div class="box"><header class="header"><van-nav-bartitle="嗨购登录"left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="form" v-if="type === '1'"><van-field v-model="loginname" placeholder="用户名/手机号/邮箱" clearable/><van-field v-model="password" type="password" placeholder="请输入密码" clearable/><p class="passwordTip" v-if="passwordTipFlag">输入至少6位,包含至少一个大写字母,1个小写字母,1个数字</p><div class="my-button"><van-button color="#ff6666" :disabled="adminameFlag"  block round @click="adminameLoginFn">登录</van-button></div></div><div class="form" v-if="type === '0'"><van-field v-model="tel" type="tel" placeholder="手机号码" clearable/><van-fieldv-model="telcode"centerclearableplaceholder="请输入短信验证码"><template #button><van-button size="small" >发送短信验证码</van-button></template></van-field><div class="my-button"><van-button color="#ff6666"  block round>登录</van-button></div></div><!-- 登录方式以及 注册提示 --><ul class="more"><li @click="changeType"><span v-if="type === '1'">短信验证码登录</span><span v-else>账号密码登录</span></li><router-link to="/register/step1" tag="li">手机快速注册</router-link></ul><div class="my-divider"><van-divider>其他登录方式</van-divider></div><div class="my-login-type"><van-row type="flex" justify="center"><van-col span="6"><van-image :src="qq" width="48" height="48"/><p>QQ</p></van-col><van-col span="6"><van-image :src="wx" width="48" height="48"/><p>微信</p></van-col><van-col span="6"><van-image :src="apple" width="48" height="48"/><p>苹果</p></van-col></van-row></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Field, Button, Divider, Col, Row, Image as VanImage } from 'vant'
import { mapActions } from 'vuex'
Vue.use(NavBar)
Vue.use(Field)
Vue.use(Button)
Vue.use(Divider)
Vue.use(Col)
Vue.use(Row)
Vue.use(VanImage)
export default {data () {return {qq: 'data:image/png;base64,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',wx: 'data:image/png;base64,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',apple: 'data:image/png;base64,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',tel: '',password: '',loginname: '',telcode: '',type: '1' // 1表示账户名密码 0表示手机验证码}},computed: {adminameFlag () {if (this.loginname !== '' && /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/.test(this.password)) {return false} else {return true}},passwordTipFlag () {if (this.password === '' || /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/.test(this.password)) {return false} else {return true}}},methods: {...mapActions({loginAction: 'user/loginAction'}),changeType () {this.type = this.type === '1' ? '0' : '1'},adminameLoginFn () {console.log('1111111')// 异步操作// this.$store.dispatch('user/loginAction', {//   loginname: this.loginname,//   password: this.password// })this.loginAction({loginname: this.loginname,password: this.password})}}
}
</script>
​
<style lang="stylus">
.container .box .contentpadding 30px 15pxbackground-color #ffffff
​
.form.my-buttonmargin-top 30px
.moremargin-top 20pxdisplay flexliflex 1&:nth-child(1)text-align left&:nth-child(2)text-align right
.my-dividermargin-top 80px
.passwordTipcolor #f66font-size 12px
</style>
​

15.4 退出时改变状态

s r c/views/user/idnex.vue

<template><div class="box"><header class="header">user header</header><div class="content">
​<button v-if="loginState" @click="logout">退出</button><button v-else @click="login"> 登录</button>{{ listLen }}</div></div>
</template>
<script>
import { mapState, mapMutations, mapGetters } from 'vuex'
export default {computed: {// loginState () {//   return this.$store.state.user.loginState// }...mapState({loginState: state => state.user.loginState}),// listLen () {//   return this.$store.getters.len// }...mapGetters({listLen: 'len'})},methods: {...mapMutations({changeLoginState: 'user/changeLoginState' // key随意 - 事件,value即为mutation中的值,一般情况下二者相同}),logout () {localStorage.removeItem('token')localStorage.removeItem('userid')localStorage.removeItem('loginState')// this.$storemit('user/changeLoginState', false) // 二次渲染的关键this.changeLoginState(false) // 事件中通过 this.key事件(参数)this.$router.push('/login')},login () {this.$router.push('/login')}}
}
</script>
​

16.使用状态管理器管理购物车的数据 - 作业

16.1 添加模块

s r c/store/cart.js

import { getCartList } from './../../api/cart'
export default {namespaced: true,state: {cartList: []},mutations: {changeCartList (state, data) {state.cartList = data}},actions: {getCartListAction (context, params) {return new Promise(resolve => {// 后续的操作交给组件getCartList(params).then(res => {resolve(res)})})}}
}
​

16.2 注册模块

// src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import cart from './modules/cart'
Vue.use(Vuex)
​
export default new Vuex.Store({state: {},mutations: {},actions: {},getters: { // 可以看作状状态管理器的计算属性showNum (state) { // 控制底部选项卡中数量显示还是不显示// state 这个参数其实就是 所有的状态return state.user.isLogin},totalNum (state) { // 判断很关键return state.cart.cartList && state.cart.cartList.reduce((sum, item) => {return item.flag ? sum + item.num : sum + 0}, 0)},totalPrice (state) {return state.cart.cartList && state.cart.cartList.reduce((sum, item) => {return item.flag ? sum + item.originprice * item.num : sum + 0}, 0) * 100}},modules: {user,cart}
})
​

16.3 组件使用状态

s r c/views/cart/index.vue

<template><div class="box"><header class="header"><van-nav-bar:title="'购物车-' + totalNum"left-arrow@click-left="$router.back()"/></header><div class="content"><div v-if="empty"><van-empty description="购物车空空如也"><router-link to="/kind"><van-button round type="danger" class="bottom-button">立即选购</van-button></router-link></van-empty></div><div v-else><van-row v-for="item of cartList" :key="item.cartid"><van-col span="3" class="checkboxList"><van-checkbox @change="updateFlag(item.cartid, item.flag)" v-model="item.flag"></van-checkbox></van-col><van-col span="21"><van-swipe-cell><van-card:price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper @change="updateNum(item.cartid, item.num)" v-model="item.num" max="5" theme="round" button-size="22" /></template></van-card><template #right><van-button @click="removeItem(item.cartid)" square text="删除" type="danger" class="delete-button" /></template></van-swipe-cell></van-col></van-row><van-submit-bar :disabled="flag" :price="totalPrice" button-text="提交订单" @submit="onSubmit"><van-checkbox @click="updateAllFlag" v-model="checked">全选</van-checkbox></van-submit-bar></div></div></div>
</template>
<script>
import Vue from 'vue'
import { mapState, mapActions, mapMutations, mapGetters } from 'vuex'
import { NavBar, Stepper, Empty, Button, Col, SubmitBar, Row, Card, Checkbox, SwipeCell } from 'vant'
import { remove, updateCartNum, selectall, selectone } from './../../api/cart'
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Col)
Vue.use(Row)
Vue.use(Checkbox)
Vue.use(Card)
Vue.use(SwipeCell)
Vue.use(Stepper)
Vue.use(SubmitBar)
export default {data () {return {// cartList: [], // 8.删除购物车的初始化状态empty: true,checked: false}},computed: {// 1.获取状态管理器中的登录状态...mapState({isLogin: state => state.user.isLogin,// 9.获取购物车中的状态cartList: state => state.cart.cartList}),// 10.获取vuex中的totalNum - 不添加命名空间...mapGetters({// key 代表当前组件中需要的字段,value代表的是vuex中的 getters中设置的计算属性totalNum: 'totalNum',totalPrice: 'totalPrice'}),// totalNum () {//   return this.cartList.reduce((sum, item) => {//     return item.flag ? sum + item.num : sum + 0//   }, 0)// },// totalPrice () {//   return this.cartList.reduce((sum, item) => {//     return item.flag ? sum + item.originprice * item.num : sum + 0//   }, 0) * 100// },flag () { // 提交订单按钮可点不可点return this.totalNum <= 0}},methods: {// 3.生成获取购物车数据的方法...mapActions({getCartListAction: 'cart/getCartListAction'}),// 5.生成修改购物车数据的方法...mapMutations({changeCartList: 'cart/changeCartList'}),onSubmit () {},updateFlag (cartid, flag) {console.log(cartid, flag)selectone({cartid, flag}).then(res => {this.getCartListData()})},updateAllFlag () {selectall({userid: localStorage.getItem('userid'),type: this.checked}).then(res => {this.getCartListData()})},getCartListData () {// 4.调用vuex中的actionsthis.getCartListAction({ userid: localStorage.getItem('userid') }).then(res => {// 没有数据if (res.data.code === '10020') {this.empty = true// 6.修改vuex中的状态this.changeCartList([])} else {this.empty = false// 7.修改vuex中的状态this.changeCartList(res.data.data)// 判断全选是不是被选中// every 所有的条件都满足返回为true,只要有一个不满足返回为falsethis.checked = res.data.data.every(item => item.flag)}})},updateNum (cartid, num) {console.log(cartid, num)updateCartNum({cartid,num}).then(res => {this.getCartListData() // 重新获取最新的数据})},removeItem (cartid) {remove({cartid}).then(res => {this.getCartListData() // 重新获取最新的数据})}},mounted () {// 2.依据状态管理器中的登录状态进一步操作if (this.isLogin) {this.getCartListData()} else {this.$router.push('/login')}}
}
</script>
<style lang="stylus" scoped>
.checkboxListdisplay flexheight 1.04remjustify-content centeralign-items centerbackground-color #fafafa
.delete-button {height: 100%;
}
</style>
​

16.4 添加底部的数量标签

s r c/app.vue

<template><div class="container"><!-- <div class="box"><header class="header">header</header><div class="content">content</div></div> --><router-view></router-view><footer class="footer" v-if="!$route.meta.hidden"><ul><!-- router-link 默认会渲染为 a 标签使用tag属性设置 转换的标签 --><router-link to="/home" tag="li"><span class="iconfont icon-shouye"></span><p>首页</p></router-link><router-link to="/kind" tag="li"><span class="iconfont icon-leimupinleifenleileibie"></span><p>分类</p></router-link><router-link to="/cart" tag="li"><span class="iconfont icon-shopping-cart"></span><p>购物车{{ isLogin ? totalNum : ''}}</p></router-link><router-link v-if="isLogin" to="/user" tag="li"><span class="iconfont icon-wode"></span><p>我的</p></router-link><router-link v-else to="/login" tag="li"><span class="iconfont icon-wode"></span><p>未登录</p></router-link></ul></footer><div class="tip">请将屏幕竖向浏览</div></div>
</template>
<script>
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
// 组件中获取状态管理器的状态可以使用计算属性
export default {methods: { // 2.页面的刷新,导致数据的重置,获取最新的数据...mapActions({getCartListAction: 'cart/getCartListAction'}),...mapMutations({changeCartList: 'cart/changeCartList'})},mounted () { // 3.获取实时的购物车中的数据this.getCartListAction({ userid: localStorage.getItem('userid') }).then(res => {if (res.data.code === '10020') {this.changeCartList([])} else {this.changeCartList(res.data.data)}})},computed: {// isLogin () {//   return this.$store.state.user.isLogin// }// ... 扩展运算符其实代表的就是合并对象// computed 是一个对象,还可以写其他的自定义的计算属性...mapState({ // 使用mapState辅助函数获取状态管理器中的状态,结合 扩展运算符完成isLogin: state => state.user.isLogin
​}),// 1.获取购物车中的数量...mapGetters({totalNum: 'totalNum'})}
}
</script>
​
<style lang="stylus">
。。。。
</style>
​

16.5 详情页面底部的数量

<template><div class="box"><header class="header"><!-- 使用导航栏组件 --><van-nav-bar:title="proname"left-arrow@click-left="$router.back()"><template #right><!-- 头部右侧的下拉选择菜单 --><van-popoverv-model="showPopover"theme="dark"trigger="click":actions="actions"placement="bottom-end"@select = "moreEvent"><template #reference><van-icon name="more-o" size="18"/></template></van-popover>
​</template></van-nav-bar></header><div class="content"><van-swipe class="detail-swipe" indicator-color="white"><van-swipe-item @click="previewImage(index)" v-for="(item, index) of banners" :key="index"><van-imagefit="cover":src="item"/></van-swipe-item></van-swipe><!-- 播放视频的图标 --><van-icon v-if="flag" @click="openOverLay" name="play-circle-o" class="playBtn" size="36" color="#f66"/><!-- 详情 --><van-tag type="danger">{{ brand }}</van-tag> {{ category }}<h3>{{ proname }}</h3><div>{{ originprice }}</div>
​<van-goods-action><van-goods-action-icon icon="chat-o" text="客服" color="#ee0a24" /><!-- 2.展示数量 --><van-goods-action-icon icon="cart-o" text="购物车" :badge=" isLogin && totalNum > 0 ? totalNum : ''" /><van-goods-action-icon icon="star" text="已收藏" color="#ff5000" /><van-goods-action-button type="warning" @click="addProToCart" text="加入购物车" /><van-goods-action-button type="danger" text="立即购买" /></van-goods-action><!-- 分享面板 --><van-share-sheetv-model="showShare"title="立即分享给好友":options="options"/></div><!-- 视频播放的遮罩层 --><van-overlay :show="show" @click="closeOverLay" class="vdoBox"><video ref="vdo" width="100%" src=".f20.mp4?dockingId=f782a297-b570-4701-bcea-9ae0c0749efe&storageSource=3" controls></video></van-overlay>
​</div>
</template>
<script>
import Vue from 'vue'
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
import { getProDetail } from './../../api/detail'
import { addCart } from './../../api/cart'
import { Toast, ImagePreview, Overlay, ShareSheet, Popover, NavBar, Swipe, SwipeItem, Tag, GoodsAction, GoodsActionIcon, GoodsActionButton } from 'vant'
Vue.use(Toast)
Vue.use(ImagePreview)
Vue.use(Overlay)
Vue.use(ShareSheet)
Vue.use(Popover)
Vue.use(NavBar)
Vue.use(Swipe)
Vue.use(SwipeItem)
Vue.use(Tag)
Vue.use(GoodsAction)
Vue.use(GoodsActionIcon)
Vue.use(GoodsActionButton)
export default {computed: {//...mapState({isLogin: state => state.user.isLogin}),// 1.获取vuex中的totalNum数量...mapGetters({totalNum: 'totalNum'})},data () {return {proid: '',proname: '',originprice: 0,discount: 0,banners: [],sales: 0,category: '',brand: '',showPopover: false, // 控制右侧更多菜单的显示和隐藏actions: [{ text: '首页' }, { text: '分类' }, { text: '购物车' }, { text: '我的' }, { text: '分享' }],showShare: false, // 控制分享面板的显示和隐藏options: [ // 分享面板{ name: '微信', icon: 'wechat' },{ name: '微博', icon: 'weibo' },{ name: '复制链接', icon: 'link' },{ name: '分享海报', icon: 'poster' },{ name: '二维码', icon: 'qrcode' }],show: false, // 控制视频播放遮罩层的显示和隐藏flag: true // 控制播放按钮的显示和隐藏}},mounted () {this.proid = this.$route.params.proidgetProDetail(this.proid).then(res => {console.log(res)// 当前接口的banenrs数据有问题,需要前端自行处理 ---- 不意味着以后别的项目也需要this.banners = res.data.data.banners[0].split(',')this.proname = res.data.data.pronamethis.originprice = res.data.data.originpricethis.discount = res.data.data.discountthis.sales = res.data.data.salesthis.category = res.data.data.categorythis.brand = res.data.data.brand})},methods: {// 3.为了加入购物车之后更新数据...mapActions({getCartListAction: 'cart/getCartListAction'}),...mapMutations({changeCartList: 'cart/changeCartList'}),addProToCart () {// 前端校验登录  本地存储的都是字符串if (localStorage.getItem('isLogin') === 'true') { // 前端已经表示登录// 调用加入购物车接口addCart({ // 一定要把参数传递完整,否则会有小发现userid: localStorage.getItem('userid'),proid: this.proid,num: 1}).then(res => {Toast('加入购物车成功')// 4.更新购物车的数据this.getCartListAction({ userid: localStorage.getItem('userid') }).then(res => {if (res.data.code === '10020') {this.changeCartList([])} else {this.changeCartList(res.data.data)}})})} else {this.$router.push('/login')}},previewImage (index) {ImagePreview({ // 预览图片images: this.banners,startPosition: index})},openOverLay () { // 打开遮罩层,播放视频,隐藏按钮this.show = truethis.flag = falsethis.$refs.vdo.play()},closeOverLay () { // 关闭遮罩层,暂停视频,显示按钮this.$refs.vdo.pause()this.flag = truethis.show = false},moreEvent (action, index) { // 右上角更多菜单console.log(index, action)switch (index) {case 0:this.$router.push('/home')breakcase 1:this.$router.push('/kind')breakcase 2:this.$router.push('/cart')breakcase 3:this.$router.push('/user')breakcase 4:this.showShare = true // 控制分享面板的显示breakdefault:break}}}
}
</script>
​
<style lang="stylus">
.detail-swipeheight 2.6rem
.van-popover[data-popper-placement=bottom-end] .van-popover__arrow {right: 0px;
}
.playBtnposition fixedtop 2.4remleft 50%transform translateX(-50%)z-index 1000
.vdoBoxdisplay flexjustify-content centeralign-items center
</style>
​

如果删掉本地存储的数据,当用户在首页后者详情页面重新刷新页面时,自动跳转到了 登录页面, ------ qq 微信

但是我们希望 首页,分类,详情,活动,即使用户不登录也可以查看 ---- 修改axios的配置

// /
import axios from 'axios'
import router from './../router'
import store from './../store' // **************************重中之重****************************************
// 开发环境 yarn serve
// 生产环境 yarn build
// development  production
const isDev = process.env.NODE_ENV === 'development'
​
// 创建axios实例
// 
const request = axios.create({// baseUrl 实际请求的地址是 baseURL + 请求地址// http://121.89.205.189/api/banner/list  ===》 baseURL + '/banner/list'// baseURL: 'http://121.89.205.189/api',// 项目上线时无需修改baseURL地址 ---- 需要提前知道线上接口的地址// baseURL: isDev ? 'http://121.89.205.189/api' : 'http://121.89.205.189/api',// 如果使用了 代理 解决跨域问题baseURL: isDev ? '' : 'http://121.89.205.189/api',timeout: 6000 // 网络超时时间
})
​
// axios 的拦截器
// 
// 请求拦截器 ---- 所有的数据在请求之前都会执行的代码 --- 显示loading的动画效果/给接口添加token
request.interceptors.request.use((config) => {// 在请求之前做些什么// 给所有的请求都传递token信息config.headersmon.token = localStorage.getItem('token') || ''return config
}, (error) => {return Promise.reject(error)
})
// 响应拦截器 ---- 在拿到接口的数据之前都会执行的代码 --- 隐藏loading的动画效果/验证token
request.interceptors.response.use((response) => {// 在响应时做些什么// token 没有传递  token 传递了只不过是错误的  token 传递了 失效了if (response.data.code === '10119') {console.log(111111111)// 引入路由器,跳转到登录页面 ****************************重中之重****************************************if (store.state.user.isLogin) {router.push('/login')}}return response
}, (error) => {return Promise.reject(error)
})
​
// 暴露自定义的axios
export default request
​

16.6 总结

  • 选择是否需要分模块(不管项目大小都可分 - 参照16点,但是一般小项目部分模块 - 参照 15点)

  • 分模块步骤

    • 1.先写模块(state, mutations, actions, namespaced)

    namespaced 是关键,使用 mutations 和 actions 时需要 指明模块的名称

    • 2.注册模块 (state, getters, mutations, actions, modules)

    modules是关键,它的key就是模块的名称

    getters 是计算属性

    state 可以是 所有组件都需要的模块的状态

    • 3.组件中使用辅助函数执行业务(mapState, mapGetters,mapMutations, mapActions)

更多推荐

VueDemo

本文发布于:2024-03-06 05:36:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1714501.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:VueDemo

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!