• Vue学习笔记之Vuex 6.25


    Vuex

    1.概念

    ​ 在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

    2.何时使用?

    ​ 多个组件需要共享数据时

    3.搭建vuex环境

    1. 创建文件:src/store/index.js

      //引入Vue核心库
      import Vue from 'vue'
      //引入Vuex
      import Vuex from 'vuex'
      //应用Vuex插件
      Vue.use(Vuex)
      
      //准备actions对象——响应组件中用户的动作
      const actions = {}
      //准备mutations对象——修改state中的数据
      const mutations = {}
      //准备state对象——保存具体的数据
      const state = {}
      
      //创建并暴露store
      export default new Vuex.Store({
      	actions,
      	mutations,
      	state
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    2. main.js中创建vm时传入store配置项

      ......
      //引入store
      import store from './store'
      ......
      
      //创建vm
      new Vue({
      	el:'#app',
      	render: h => h(App),
      	store
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

    4.基本使用

    1. 初始化数据、配置actions、配置mutations,操作文件store.js

      //引入Vue核心库
      import Vue from 'vue'
      //引入Vuex
      import Vuex from 'vuex'
      //引用Vuex
      Vue.use(Vuex)
      
      const actions = {
          //响应组件中加的动作
      	jia(context,value){
      		// console.log('actions中的jia被调用了',miniStore,value)
      		context.commit('JIA',value)
      	},
      }
      
      const mutations = {
          //执行加
      	JIA(state,value){
      		// console.log('mutations中的JIA被调用了',state,value)
      		state.sum += value
      	}
      }
      
      //初始化数据
      const state = {
         sum:0
      }
      
      //创建并暴露store
      export default new Vuex.Store({
      	actions,
      	mutations,
      	state,
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
    2. 组件中读取vuex中的数据:$store.state.sum

    3. 组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)$store.commit('mutations中的方法名',数据)

      备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

    5.getters的使用

    1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。

    2. store.js中追加getters配置

      ......
      
      const getters = {
      	bigSum(state){
      		return state.sum * 10
      	}
      }
      
      //创建并暴露store
      export default new Vuex.Store({
      	......
      	getters
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    3. 组件中读取数据:$store.getters.bigSum

    6.四个map方法的使用

    1. mapState方法:用于帮助我们映射state中的数据为计算属性

      computed: {
          //借助mapState生成计算属性:sum、school、subject(对象写法)
           ...mapState({sum:'sum',school:'school',subject:'subject'}),
               
          //借助mapState生成计算属性:sum、school、subject(数组写法)
          ...mapState(['sum','school','subject']),
      },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性

      computed: {
          //借助mapGetters生成计算属性:bigSum(对象写法)
          ...mapGetters({bigSum:'bigSum'}),
      
          //借助mapGetters生成计算属性:bigSum(数组写法)
          ...mapGetters(['bigSum'])
      },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    3. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

      methods:{
          //靠mapActions生成:incrementOdd、incrementWait(对象形式)
          ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
      
          //靠mapActions生成:incrementOdd、incrementWait(数组形式)
          ...mapActions(['jiaOdd','jiaWait'])
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

      methods:{
          //靠mapActions生成:increment、decrement(对象形式)
          ...mapMutations({increment:'JIA',decrement:'JIAN'}),
          
          //靠mapMutations生成:JIA、JIAN(对象形式)
          ...mapMutations(['JIA','JIAN']),
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。

    7.模块化+命名空间

    1. 目的:让代码更好维护,让多种数据分类更加明确。

    2. 修改store.js

      const countAbout = {
        namespaced:true,//开启命名空间
        state:{x:1},
        mutations: { ... },
        actions: { ... },
        getters: {
          bigSum(state){
             return state.sum * 10
          }
        }
      }
      
      const personAbout = {
        namespaced:true,//开启命名空间
        state:{ ... },
        mutations: { ... },
        actions: { ... }
      }
      
      const store = new Vuex.Store({
        modules: {
          countAbout,
          personAbout
        }
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
    3. 开启命名空间后,组件中读取state数据:

      //方式一:自己直接读取
      this.$store.state.personAbout.list
      //方式二:借助mapState读取:
      ...mapState('countAbout',['sum','school','subject']),
      
      • 1
      • 2
      • 3
      • 4
    4. 开启命名空间后,组件中读取getters数据:

      //方式一:自己直接读取
      this.$store.getters['personAbout/firstPersonName']
      //方式二:借助mapGetters读取:
      ...mapGetters('countAbout',['bigSum'])
      
      • 1
      • 2
      • 3
      • 4
    5. 开启命名空间后,组件中调用dispatch

      //方式一:自己直接dispatch
      this.$store.dispatch('personAbout/addPersonWang',person)
      //方式二:借助mapActions:
      ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
      
      • 1
      • 2
      • 3
      • 4
    6. 开启命名空间后,组件中调用commit

      //方式一:自己直接commit
      this.$store.commit('personAbout/ADD_PERSON',person)
      //方式二:借助mapMutations:
      ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
      
      • 1
      • 2
      • 3
      • 4

    路由

    1. 理解: 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。
    2. 前端路由:key是路径,value是组件。

    1.基本使用

    1. 安装vue-router,命令:npm i vue-router

    2. 应用插件:Vue.use(VueRouter)

    3. 编写router配置项:

      //引入VueRouter
      import VueRouter from 'vue-router'
      //引入Luyou 组件
      import About from '../components/About'
      import Home from '../components/Home'
      
      //创建router实例对象,去管理一组一组的路由规则
      const router = new VueRouter({
      	routes:[
      		{
      			path:'/about',
      			component:About
      		},
      		{
      			path:'/home',
      			component:Home
      		}
      	]
      })
      
      //暴露router
      export default router
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
    4. 实现切换(active-class可配置高亮样式)

      <router-link active-class="active" to="/about">About</router-link>
      
      • 1
    5. 指定展示位置

      <router-view></router-view>
      
      • 1

    2.几个注意点

    1. 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。
    2. 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
    3. 每个组件都有自己的$route属性,里面存储着自己的路由信息。
    4. 整个应用只有一个router,可以通过组件的$router属性获取到。

    3.多级路由(多级路由)

    1. 配置路由规则,使用children配置项:

      routes:[
      	{
      		path:'/about',
      		component:About,
      	},
      	{
      		path:'/home',
      		component:Home,
      		children:[ //通过children配置子级路由
      			{
      				path:'news', //此处一定不要写:/news
      				component:News
      			},
      			{
      				path:'message',//此处一定不要写:/message
      				component:Message
      			}
      		]
      	}
      ]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    2. 跳转(要写完整路径):

      <router-link to="/home/news">News</router-link>
      
      • 1

    4.路由的query参数

    1. 传递参数

      <!-- 跳转并携带query参数,to的字符串写法 -->
      <router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
      				
      <!-- 跳转并携带query参数,to的对象写法 -->
      <router-link 
      	:to="{
      		path:'/home/message/detail',
      		query:{
      		   id:666,
                  title:'你好'
      		}
      	}"
      >跳转</router-link>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    2. 接收参数:

      $route.query.id
      $route.query.title
      
      • 1
      • 2

    5.命名路由

    1. 作用:可以简化路由的跳转。

    2. 如何使用

      1. 给路由命名:

        {
        	path:'/demo',
        	component:Demo,
        	children:[
        		{
        			path:'test',
        			component:Test,
        			children:[
        				{
                              name:'hello' //给路由命名
        					path:'welcome',
        					component:Hello,
        				}
        			]
        		}
        	]
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
      2. 简化跳转:

        <!--简化前,需要写完整的路径 -->
        <router-link to="/demo/test/welcome">跳转</router-link>
        
        <!--简化后,直接通过名字跳转 -->
        <router-link :to="{name:'hello'}">跳转</router-link>
        
        <!--简化写法配合传递参数 -->
        <router-link 
        	:to="{
        		name:'hello',
        		query:{
        		   id:666,
                    title:'你好'
        		}
        	}"
        >跳转</router-link>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16

    6.路由的params参数

    1. 配置路由,声明接收params参数

      {
      	path:'/home',
      	component:Home,
      	children:[
      		{
      			path:'news',
      			component:News
      		},
      		{
      			component:Message,
      			children:[
      				{
      					name:'xiangqing',
      					path:'detail/:id/:title', //使用占位符声明接收params参数
      					component:Detail
      				}
      			]
      		}
      	]
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    2. 传递参数

      <!-- 跳转并携带params参数,to的字符串写法 -->
      <router-link :to="/home/message/detail/666/你好">跳转</router-link>
      				
      <!-- 跳转并携带params参数,to的对象写法 -->
      <router-link 
      	:to="{
      		name:'xiangqing',
      		params:{
      		   id:666,
                  title:'你好'
      		}
      	}"
      >跳转</router-link>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!

    3. 接收参数:

      $route.params.id
      $route.params.title
      
      • 1
      • 2

    7.路由的props配置

    ​ 作用:让路由组件更方便的收到参数

    {
    	name:'xiangqing',
    	path:'detail/:id',
    	component:Detail,
    
    	//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
    	// props:{a:900}
    
    	//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
    	// props:true
    	
    	//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
    	props(route){
    		return {
    			id:route.query.id,
    			title:route.query.title
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    8.<router-link>的replace属性

    1. 作用:控制路由跳转时操作浏览器历史记录的模式
    2. 浏览器的历史记录有两种写入方式:分别为pushreplacepush是追加历史记录,replace是替换当前记录。路由跳转时候默认为push
    3. 如何开启replace模式:<router-link replace .......>News</router-link>

    9.编程式路由导航

    1. 作用:不借助<router-link> 实现路由跳转,让路由跳转更加灵活

    2. 具体编码:

      //$router的两个API
      this.$router.push({
      	name:'xiangqing',
      		params:{
      			id:xxx,
      			title:xxx
      		}
      })
      
      this.$router.replace({
      	name:'xiangqing',
      		params:{
      			id:xxx,
      			title:xxx
      		}
      })
      this.$router.forward() //前进
      this.$router.back() //后退
      this.$router.go() //可前进也可后退
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

    10.缓存路由组件

    1. 作用:让不展示的路由组件保持挂载,不被销毁。

    2. 具体编码:

      <keep-alive include="News"> 
          <router-view></router-view>
      </keep-alive>
      
      • 1
      • 2
      • 3

    11.两个新的生命周期钩子

    1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
    2. 具体名字:
      1. activated路由组件被激活时触发。
      2. deactivated路由组件失活时触发。

    12.路由守卫

    1. 作用:对路由进行权限控制

    2. 分类:全局守卫、独享守卫、组件内守卫

    3. 全局守卫:

      //全局前置守卫:初始化时执行、每次路由切换前执行
      router.beforeEach((to,from,next)=>{
      	console.log('beforeEach',to,from)
      	if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
      		if(localStorage.getItem('school') === 'atguigu'){ //权限控制的具体规则
      			next() //放行
      		}else{
      			alert('暂无权限查看')
      			// next({name:'guanyu'})
      		}
      	}else{
      		next() //放行
      	}
      })
      
      //全局后置守卫:初始化时执行、每次路由切换后执行
      router.afterEach((to,from)=>{
      	console.log('afterEach',to,from)
      	if(to.meta.title){ 
      		document.title = to.meta.title //修改网页的title
      	}else{
      		document.title = 'vue_test'
      	}
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    4. 独享守卫:

      beforeEnter(to,from,next){
      	console.log('beforeEnter',to,from)
      	if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
      		if(localStorage.getItem('school') === 'atguigu'){
      			next()
      		}else{
      			alert('暂无权限查看')
      			// next({name:'guanyu'})
      		}
      	}else{
      		next()
      	}
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    5. 组件内守卫:

      //进入守卫:通过路由规则,进入该组件时被调用
      beforeRouteEnter (to, from, next) {
      },
      //离开守卫:通过路由规则,离开该组件时被调用
      beforeRouteLeave (to, from, next) {
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    13.路由器的两种工作模式

    1. 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。

    2. hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。

    3. hash模式:

      1. 地址中永远带着#号,不美观 。
      2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
      3. 兼容性较好。
    4. history模式:

      1. 地址干净,美观 。
      2. 兼容性和hash模式相比略差。
      3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。

      //全局后置守卫:初始化时执行、每次路由切换后执行
      router.afterEach((to,from)=>{
      console.log(‘afterEach’,to,from)
      if(to.meta.title){
      document.title = to.meta.title //修改网页的title
      }else{
      document.title = ‘vue_test’
      }
      })

      
      
      • 1
    5. 独享守卫:

      beforeEnter(to,from,next){
      	console.log('beforeEnter',to,from)
      	if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
      		if(localStorage.getItem('school') === 'atguigu'){
      			next()
      		}else{
      			alert('暂无权限查看')
      			// next({name:'guanyu'})
      		}
      	}else{
      		next()
      	}
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    6. 组件内守卫:

      //进入守卫:通过路由规则,进入该组件时被调用
      beforeRouteEnter (to, from, next) {
      },
      //离开守卫:通过路由规则,离开该组件时被调用
      beforeRouteLeave (to, from, next) {
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    13.路由器的两种工作模式

    1. 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。
    2. hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
    3. hash模式:
      1. 地址中永远带着#号,不美观 。
      2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
      3. 兼容性较好。
    4. history模式:
      1. 地址干净,美观 。
      2. 兼容性和hash模式相比略差。
      3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。
  • 相关阅读:
    【计算机视觉 | 目标检测】arxiv 计算机视觉关于分类和分割的学术速递(6月 22 日论文合集)
    Telnet 测试 UDP 端口?
    Eureka应用及高可用集群
    代码审计-3 文件包含漏洞
    C# 图片转PDF,PDF增加水印文字
    scitb包1.5版本发布—增加了统计值的结果和自动判断数据是否正态分布的功能
    智云通CRM:如何进行大客户复杂关系的识别?
    ​力扣解法汇总792. 匹配子序列的单词数
    Kafka学习
    基于java校园二手物品交易系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
  • 原文地址:https://blog.csdn.net/qq_36450483/article/details/125464422