vue2学习笔记(供参考)

一. Vue基础

认识Vue.js

Vue是一个渐进式的框架

  1. 渐进式意味着你可以将Vue作为你应用的一部分嵌套其中
  2. Vue的核心库以及其生态系统
  3. 全家桶:Core + Vue-router + Vuex

Vue特点和Web开发常见高级功能

  1. 解耦视图和数据
  2. 可复用的组件
  3. 前端路由技术
  4. 状态管理
  5. 虚拟DOM

Vue安装方式

方式一. 直接CDN引入
可以选择引入开发环境版本 / 生产环境版本

// 开发环境版本, 包含了帮助的命令行警告
<srcipt src='https://cdn.jsdeliver.net/npm/vue/dist/vue.js'></script>
// 生产环境版本, 优化了尺寸和速度
<srcipt src='https://cdn.jsdeliver.net/npm/vue'></script>

方式二. 下载和引入

// 开发环境
https://vuejs.org/js/vue.js

// 生产环境
https://vuejs.org/js/vue.min.js

方式三. NPM安装

通过webpack和CLI的使用

Vue的MVVM

M: Model 数据模型
  • 数据层
  • 数据可能是固定的思数据, 更多的是来自服务器, 从网络上请求下来的数据
  • V: View 视图模板
V: View 视图模板
  • 视觉层
  • 在前端开发中, 通常是DOM层
  • 作用: 是给用户展示各种信息
VM: View-Model 视图模型
  • 视图模型层
  • 是View和Model沟通的桥梁
  • 一方面实现了Data Binding (数据绑定), 讲Model的改变实时的反应到View中
  • 另一方面实现了DOM Listener (DOM监听), 当DOM发生一些时间 (点击, 滚动, touch等) 时, 可以监听到, 并在需要的情况下改变对应的Data

二. Vue基础语法

插值语法:

  1. {{可以是Vuedata中的数据。或者js表达式}}

vue指令:

  1. v-html: 渲染html内容

  2. v-text:渲染html内容但是不会识别字符串标签

  3. v-model:实现表单元素和数据的双向绑定

  4. v-bind:动态绑定属性语法糖为 ‘

  5. v-once: 后面不需要跟任何表达式表示元素和组件只渲染一次, 不会随着数据的改变而变化

  6. v-if:条件判断 v-if v-else-if v-else

  7. v-show: 当条件为false时元素隐藏,相当于display:none v-if不会渲染到页面

  8. v-cloak:当页面加载缓慢,vm还未接管页面时网页源代码会出现,添加完v-cloak后页面会元素会成为display:none,vm接管页面后显示;

  9. v-on: 绑定事件语法糖为’@‘,不用传参时,可以直接写函数名,传参时调用括号内传入实参,需要事件对象时传入**’'$event"**

事件修饰符

作用

实际调用

  1. stop :阻止事件冒泡 === event.stopPropagation()

  2. prevent: 阻止默认事件 === event.preventDefault()

  3. once:执行一次

v-for遍历数组

// 遍历数组item为每个元素,index为数组下标
<li v-for="(item,index) in names">{{item}}</li>
//遍历对象时item为每个对象的属性值,key为每个对象的属性名index为数组下标
<li v-for="(item,key,index) in names">{{item}}</li>

官方提示:v-for 在循环时加上key值

key的作用为向虚拟DOM添加一个id值,从而更高效的更新虚拟DOM,这个id必须为唯一值,不然就没有意义

diff算法:

  • 在页面创建时vue会先在内存中生成一个虚拟DOM,并且会在虚拟DOM中添加key值,当data中数据发生改变触发页面元素更新的时候,会再次生成新的虚拟DOM,新旧虚拟DOM根据key值匹配进行对比,如果内容发生改变就会更新对应的真实节点,内容没变就不会更换新

data配置

  • data是Vue实例中一个配置项。用来存储vue实例或者组件里面的数值。
  • 当data存在于Vue实例中时,它既可以是以一个对象的形式(键值对)
  • data在组件中使用的时候必须以函数形式存在(因为对象是一个引用数据类型,为了防止data的属性值会互相污染, 产生副作用,这里使用了函数的返回值来创建单独的对象)

methods定义方法

  • vue 选项对象中有一个叫methods的属性.这个属性里面专门来存放一些函数,用来给别人调用

计算属性 computed

  • 使用: 需要的到一个经过复杂计算的值的时候使用
  • 不能和data中的数据名重复
  • 计算属性经过计算后的值会直接缓存,只要依赖的变量不发生变化就会不用再计算
  • 计算属性的setter和getter 一般情况没有setteer方法
	computed: {
        fullName(){
            reture 1+2
        }
    },

fulters过滤器

  • 对要现实的数据进行处理后在进行显示
  • 过滤器可以串联
在双花括号中:
    {{ date | getdate }}
 
在 v-bind 简写:中:
    <div :id="date | getdate></div>
//组件中定义过滤去
filters:{
	getdate(val){
		retrun val
	}
}
//定义全局的过滤器
Vue.filter('过滤器名曾'function(val){
    return val
})

三. 组件的使用

1、Vue组件的定义、注册方式和模板使用

1.1、组件的定义

  • vue.js中创建组件有三个步骤:定义组件,注册组件以及使用组件

    1. 第一种方式:创建一个组件构造器,然后由组件构造器创建组件 : let vm = Vue,extned({})

    2. 第二种方式:使用Vue.component(‘组件名’,{}) — { }中配置和创建vue实例时一样

    3. 第三种方式:单页面抽离组件,使用export default 抛出对象 ,对象种包含组件的配置,在需要使用的地方引入组件使用components配置注册组件,然后在页面中使用

      //第一种创建方式 创建name组件
          const name = Vue.extend({
              template:`
              <div>
                  <h2>姓名:{{name}}</h2>
              </div>
              `,
              data(){
                  return{
                      name:'爱学习的程序猿'
                  }
              }
          });
       
      
      //第二种创建方式(全局注册) 创建name组件   
      Vue.componebt('name',{
          data(){
              retrun {
                  name:'爱学习的程序猿'
              }
          },
          template:`
      		<div>
                	<h2>姓名:{{name}}</h2>
              </div>
      		`
       })
      
      //第三种方式创建组件
      export default {
          name: 'ToDoList',
          data() {
            return {
              inputVal: '',
              // data_cont: [],
              // idLength: 0
            }
          }
      }
      //在需要的地方引入
      import FalseData from './FalseData' 
      import FalseData from './TrueData' 
      components: {
            FalseData,
            TrueData
          }
      
      

2、组件之间的通信

组件可以访问VUE实例数据吗

  • 不能访问-组件是一个单独功能模块的封装 - 这个模块有自己的HTML模板, 也应该有属性自己的数据data
  • 组件中的data必须使用函数方式不然会会报错,因为对象为引用类型,为了防止data的属性值相互污染,而函数返回对象的方式会在内存中声明新的对象所以不会出现data污染的问题。

父子通讯

父向子传输数据

  1. 在父组件中使用子组件时,在子组件身上添加自定义属性,定义好属性名和要传入的值(自定义属性名不要使用驼峰式命名)
  2. 在子组件中的对象配置“props”:[‘父组件中传入的自定义属性名’] ,子组件中的props属性为数组格式,数组中的值为字符串格式。
  3. props也可以接收对象格式的,用来限制类型与传值的必要性
  4. 子组件接收到的值此时已经绑给了vc组件实例可以使用 this.属性名 直接使用
//父组件传入
<template>
    <div>	
		<Son :son='son' />
    </div>
</template>
<sctipt>
    import Son from './son'
    export default {
    name: 'ToDoList',
    data() {
      return {
       inputVal: '',
	   son:'son'
      }
    },
    components:{
    	Son
    }
}
</sctipt>
 
//子组件接收
 <template>
    <div>	
		{{son}}使用数据
    </div>
</template>
<sctipt>
    export default {
    name: 'Son',
    data() {
      return {
    	value:''
      }
    },
    //props:['son']第一种 数组格式直接接收数据
    props:{第二种 对象格式的-用来限制类型与传值的必要性
        son:{
            type:'String',//类型为字符串
            default:'son',//默认值
            required:true//为true 必传
        }
    }
}    
</sctipt>

子向父传值

  1. 自定义事件传值:在父组件中使用子组件时,在子组件身上添加自定义事件,事件会被添加到vc实例身上此时在子组件中使用 this.$emit(‘自定义事件名’,需要传入的值)对自定义事件进行调用,触发后就可以在父元素身上接收到子组件的传进来的值了

    //父组件绑定自定义事件,在事件中使用形参接收子组件传入的值
    <template>
        <div>	
    		<Son @sonclick='sonclick' />绑定自定义事件
        </div>
    </template>
    <sctipt>
        import Son from './son'
        export default {
        name: 'ToDoList',
        data() {
          return {
           inputVal: '',
          }
        },
        methods:{
            sonclick(val){//val为子组件传入的值
                console.log(val)
            }
        }
        components:{
        	Son
        }
    }
    </sctipt>
     
    //子组件使用$emit()触发事件进行传值
     <template>
        <div @click='sonclick'>	
    		我是子组件点击我触发事件
        </div>
    </template>
    <sctipt>
        export default {
        name: 'Son',
        data() {
          return {
        	value:'需要传输的值'
          }
        },
        methods:{
            sonclick(){
                this.$emit('sonclick',this.value)//调用父组件中定义的事件,使用实参的方式传值
            }
        }
    }    
    </sctipt>
    

    兄弟组件的传值

    1. 使用EventBus全局事件总线:

      1. 在创建组件时Vue.extend会帮我们创建一个全新的VueComponent的组件实例,简称 VC
      2. 这个组件实例的原型对象可以访问Vue的原型对象中的方法和属性 ‘ VC.prototype.__ proto __ === Vue.prototype
      3. 在第一个组件中使用this. b u s . bus. bus.on()添加事件
      4. 在第二个传值的组件中使用this. b u s . bus. bus.emit()触发事件传值
      //在min.js中安装全局事件总线
      new Vue({
        render: h => h(App),
        beforeCreate() {
          Vue.prototype.$bus = this//安装全局事件总线,$bus就是当前应用的Vm
        }
      }).$mount('#app')
      
      //第一个组件中接收值
      <sctipt>
          export default {
          methods:{
              friendclick(val){//val为兄弟组件传入的值
                  console.log(val)
              }
          },
          mounted(){
              this.$bus.$on('事件名',(res)=>{
                  console.log(res)//res为接收的值
              })
          }
      }
      </sctipt>
      
      //第二个组件中传值
       <template>
          <div @click='friendclick'>	
      		我是子组件点击我触发事件
          </div>
      </template>
      <sctipt>
          export default {
          methods:{
              friendclick(val){//val为兄弟组件传入的值
                  this.$bus.$emit('事件名',val)
              }
          }
      }
      </sctipt>
      
  2. $root

    $root 可以拿到 App.vue 里的数据和方法 this.$root.foo = 2; 获取根节点的数据

  3. 具名插槽+作用域插槽 slot

    1. 具名插槽是在父组件中通过slot属性,给插槽命名,在子组件中通过slot标签,根据定义好的名字填充到对应的位置。 父传子

    2. 作用域插槽是带数据的插槽,子组件提供给父组件的参数,父组件根据子组件传过来的插槽数据来进行不同的展现和填充内容。在标签中通过 v-slot=“value” 来接受数据。子传父

      // 父组件
      <template>
        <div class="">
          <HelloWorld>
            <template v-slot:a="value">
              <h2>{{ name }}</h2> // 这个是具名插槽
               <!--  value 是子组件传过来的数据 -->
              <h2>{{ value.value }}</h2> // 这个是作用域插槽
            </template>
          </HelloWorld>
        </div>
      </template>
      <script>
      import HelloWorld from "../components/HelloWorld.vue";
      export default {
        data() {
          return {
            name: "具名插槽 slot插槽传数据 父传子",
          };
        },
        components: { HelloWorld },
      };
      </script>
       
       
      // 子组件
      <template>
        <div>
          <slot name="a" :value="value"></slot>
        </div>
      </template>
      <script>
      export default {
        data() {
          return {
            value: "我是子组件数据 作用域插槽子传父 s-z-h",
          };
        },
        methods: {},
      };
      </script>
      

四、Vue生命周期

  1. Vue实例从创建到销毁的过程,就是生命周期;
  2. 从开始创建、初始化数据、编译模板、挂载dom–>渲染、更新、更新渲染、销毁等一系列过程,称之为Vue的生命周期。

vue的生命周期分为那几个阶段?

  • 8个阶段,分别是
    1. 创建前beforeCreate :实例创建之前,初始化事件还未开始,data还访问不到
    2. 创建后created :实例创建完成,完成数据监测,属性和方法的运算,初始化事件都已经完成,但是此时$el还没有显示出来,可以访问到data,computed,methods,watch
    3. 挂载前beforeMount :实例挂载之前,
    4. 挂载后mounted :实例挂载完成后
    5. 更新前beforeUpdate :组件更新之前
    6. 更新后updated :组件更新之后
    7. 销毁前beforeDestroy :实例被销毁之前现在实例还没有销毁数据依然可以拿到
    8. 销毁后destroyed:实例被销毁之后,此时data等数据已经拿不到了,但是版绑定在真实DOM事件中的事件依然可以执行

五、组件缓存

keep-alive 在vue中起到什么作用

  1. 缓存动态组件 : 组件复用,提高性能 缓存不太使用的组件,而不是直接销毁

涉及到的两个钩子函数

  1. activated:激活,**当组件在keep-alive内被切换时,**进入组件触发

  2. deactivated:失活,**当组件在keep-alive内被切换时,**离开组件触发

keep-alive 只能用在只有一个子组件的情况。如果你在其中有 v-for 则不会产生效果

keep-alive的参数有以下三种:

  1. include: [String,RegExp,Array] 只有匹配到的组件才能进行缓存

    <keep-alive include="['home']">
       <router-view />
    </keep-alive>
    
  2. exclude:[String,RegExp,Array] 匹配到的组件都不缓存

    <keep-alive exclude="['about']">
       <router-view />
    </keep-alive>
    
  3. max: [String,Number] 数字,最多能缓存多少组件实例。在新实例创建之前,缓存中最就没有使用的实例会被销毁

  4. 利用meta属性进行组件缓存

    //在路由中配置meta
    export default[
     {
      path:'/',
      name:'home',
      components:Home,
      meta:{
        keepAlive:true //需要被缓存的组件
     },
     {
      path:'/book',
      name:'book',
      components:Book,
      meta:{
         keepAlive:false //不需要被缓存的组件
     } 
    ]
    
    //组件中使用
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    

六、vue-router 路由

路由的下载创建与基本配置

  • 下载vue-router (它是一个vue插件)

    npm i vue-router -s
    
  • 在src文件夹下创建router文件夹

  • 在router中创建index.js然后引用vue-router 并配置路由

    import Vue from 'vue'
    import Router from 'vue-router'
    //使用vue.use() 安装插件
    Vue.use(Router)
    //创建路由并抛出 
    export default new Router({//路由中的配置信息
        mode:'history',//改变路由模式  哈希模式加# history模式不加#号
        routes:[{
            path: '/', // 页面默认的时候, redirect重定向
            redirect: '/home'
            },{
            name:'Home',
            path:'/home',
            component: () => import('路径'),
            redirect:'/users',//默认二级路由重定向
            children:[{//二级路由
            	name:'user',
            	path:'/user',
            	component: () => import('路径'),
        	}]
        }]
    })
    
    //在min.js中导入Router并挂载到Vue配置中
    
    import router from '@/router/index'
    // 挂载
    new Vue({
    	el: ‘#app’,
    	router,
    	render: h => h(App)
    })
    

使用路由

路由入口标签 router-view

  • 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个标签
  • 该标签会根据当前的路径, 动态渲染出不同的组件
  • 网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和处于同一个等级
  • 在路由切换时, 切换的是挂载的组件, 其他内容不会发生改变

路由跳转的方法

1、router-link 标签属性

  • 属性 to

    • 指定跳转的路径

      <router-link to="/home"></router-link>
      
  • 属性 tag

    • 可以指定之后渲染成什么组件

      <router-link to="/home" tag="li"></router-link>
      
  • 属性 replace

    • 不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中

      <router-link to="/home" replace></router-link>
      

2、 r o u t e r . p u s h ( ) 与 router.push()与 router.push()router.replace()

<div>
    <router-link @click="linkToHome"></router-link>
    <router-link @click="linkToAbout></router-link>
    <router-view></router-view>
</div>
<script>
   export default {
        name: 'App',
        methods: {
            // Vue-router在所有组件里都加入了$router 
            linkToHome () {
                // push => pushState 可以返回
                this.$router.push('./home')
            },
            linkToAbout () {
                // replace => replaceState 没有返回
                this.$router.replace('./about')
            }
        }
	}
</script>

路由传参

  • params传参

    //传参
    this.$router.push({ 
    	name:"index",    
    	//这里的params是一个对象,id是属性名,item.id是值(可以从当前组件或者Vue实例上直接取) 
    	params:{id:item.id} 
    }) 
    //这个组件对应的路由配置 
    {   
    	//组件路径 
    	path: '/index',   
    	//组件别名 
    	name: 'index',   
    	//组件名 
    	component: Index, 
    }
    //获取
        this.$route.params.id
    
  • 路由属性配置传参

    //传参
    this.$router.push({
    	name:"admin/${item.id}", 
    }) 
    //这个组件对应的路由配置 
    {   
    	//组件路径 
    	path: '/admin:id',   
    	//组件别名 
    	name: 'admin',   
    	//组件名 
    	component: Admin, 
    }
    //获取
    this.$route.params.id
    
    

    以上两种传参方式刷新页面路径中的数据会丢失

  • query传参

    //传参
    this.$router.push({
    	name:"index", 
        query:{
            id:item.id
        }
    }) 
    //这个组件对应的路由配置 
    {   
    	//组件路径 
    	path: '/index',   
    	//组件别名 
    	name: 'index',   
    	//组件名 
    	component: Index, 
    }
    //获取
    this.$route.query.id
    

区别

  1. params传参

    • 只能用 name,不能用 path。

    • 地址栏不显示参数名称 id,但是有参数的值。

  2. query传参

    • name 和 path 都能用。用 path 的时候,提供的 path 值必须是相对于根路径的相对路径,而不是相对于父路由的相对路径,否则无法成功访问。

    • 地址栏显示参数格式为?id=0&code=1

导航守卫

  • 守卫的参数

    • to: 即将要进入的目标的路由对象
    • from: 当前导航即将要离开的路由对象
    • next: 调用该方法后, 才能进入下一个钩子
  • 前置守卫

    router.beforEach((to,from,next)=>{
         //from 从哪里来
         //to 要去哪里
         //next()下一步
    })
    
  • 后置守卫 (没有next参数)

    router.afterEach(to, from) => {
    	 //from 从哪里来
         //to 要去哪里
    })
    
  • 独享守卫(路由配置时使用,是该路由独享的)

             children:[
                {
                    name:'xinwen',
                    // 二级路由不加斜杠
                    path:'news',
                    component:News,
                    meta:{
                        // 是否授权
                        isAuth:true,
                        title:'新闻'
                    },
                    beforeEnter:(to,from,next)=>{
                         //  判断是否需要鉴定一下权限
                        if(to.meta.isAuth){
                            if(localStorage.getItem('school' ) === 'atguigu'){
                                next()
                            }else{
                                alert('学校名不对,无权限查看')
                            }
                        }else{
                            next()
                        }
                    }
                    
                },
    
  • 组件内路由守卫(在组件内编写)

    //在组件中使用
    
    beforeRouteEnter((to,from,next)=>{//进入组件前调用
        //from 从哪里来
         //to 要去哪里
         //next()下一步
    }) 
    beforeRouteLeave((to,from,next)=>{//离开组件后调用 
        //from 从哪里来
         //to 要去哪里
         //next()下一步
    }) 
    

动态路由

  1. 将路由分为静态路由和动态路

  2. 静态路由就是由初始化正常加载

  3. 动态路由就是将动态获取的路由数据添加进路由表中

    //1.在router.js中
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import HomeLayout from '../layouts/HomeLayout'//静态路由的组件
    import store from '@/store/index'//引入数据仓库
    
    //2.使用前置路由守卫beforEach()
    	1.选判断token查看登录状态未登录查看是否去登录或者公共页面,是的直接放行,不是就强制去登录或首页
        2.登录后查看路由数据是否存
        3.在存在就放行,不存在就在数据仓库中后去值,
        4.数据仓库没有就向后端或本地存储中拿值,
        5.拿到以后使用addrouter()将数据添加进路由表中,然后放行
     let staticRouterMap = ['login','home','index''list']
       router.beforeEach((to, from, next) => {
    	const token = JSON.parse(sessionStorage.getItem('token'))
    	if (!token) {
    		// 没有登录
    		// 如果前往页面非公共路由,则跳转至首页
    		if (staticRouterMap.indexOf(to.name) < 0) {
    			next({name: 'home'})
    		} else {
    			next()
    		}
    	} else {
    		// 登录
    		// 已经存在路由列表: 注意刚登陆成功第一次调转route时相应store数据还未更新
    		const hasGetRoute = store.getters['user/hasGetRoute']
    		const routeMap = JSON.parse(sessionStorage.getItem('routeMap'))
    		if(!hasGetRoute && routeMap) {
                // 刷新页面且有route记录数据,可再次追加动态路由
    			store.dispatch('user/updateRouteOfUser', routeMap)
    			next({...to, replace: true})//登陆后第一次跳转,...to(解构)传入要去的页面的参数,不留下登录页的记录
    		} else {
    			next()
    		}
    	}
       }
    //权限路由     
    //在router表数据处理的时候可以添加权限处理,权限外的数据不会添加进路由表中
    //跳转之前也可以通过路由导航守卫查看白名单
    //按钮权限可以通过v-if判断
    

路由懒加载

  • 使用ES中的import进行懒加载 (推荐使用,也是最常用的)

  • 使用时在引入

    export default new Router({
      routes: [{
        path: '/',
        name: 'HelloWorld',
        component: () => import("@/components/HelloWorld")
      }]
    })
    

七、Vuex数据仓库

Vuex是做什么的

  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
    • 它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
    • Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能
  • 状态管理到底是什么
    • 状态管理模式、集中式存储管理
    • 可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面
    • 然后将这个对象放在顶层的Vue实例中,让其他组件可以使用
    • 那么多个组件是不是就可以共享这个对象中的所有变量属性了呢
  • 管理什么呢
    • 公用的信息-用户信息-路由数据-等都可以在项目中公用的信息

下载VueX

npm i vue-x -s
  • 创建store文件夹–>index.js–>module文件夹–>对应功能模块的js文件

    //在store-->index.js
    import Vue from 'vue'
    import vuex from 'vuex'
    Vue.use(vuex)//注册插件
    
    export default new vuex.Store({ //创建store实例
      state,//挂载配置对象
      mutations,
      actions,
      getters
    })
    
    //在main.js中引入’store/index.js‘
    import store from '@/store/index'
    new Vue({
      el: '#app',
      router,
      store,//使用数据仓库
      components: {
        App
      },
      template: '<App/>'
    })
    //在组件中可以通过this.$store使用数据仓库 
    

vuex的配置对象

1、State对象
  • 存放数据和状态的对象
2、Getter对象
  • 相当于vue实例中的计算属性

    	getters: {
            // state是默认参数是存放数据的state对象,可以获取数据
            // val是方法调用时传进来的参数
            getAgesCount (state,val) {
                return state.a + 1 
            }
        }
    
3、Actions对象
  • 在Actions中完成异步任务或者请求数据等操作,操作完以后在通过commit调用Mutation中的方法改变数据状态

    actions: {
            // 默认参数 context 上下文
            // 所用数据修改都要在mutations中, 所以在actions中异步后, 也要去mutations中修改 
            // 在mutations中修改, 才能被devtools监控到
            addCount (context) {
                context.commit('AddCount');//addCount是Mutation对象中的Addcount
            }
        }
    //在组件实例中调用
    this.$store.dispatch('actions的名字', 参数)
    
4、Mutation对象
  • 特点:想要修改State 中的数据,只能调用Mutation 方法,它是Vuex中用来修改公共数据的唯一入口。

  • 好处:能够确保修改来源的唯一性,方便调试和后期维护。

  • 在定义时:它的第一个参数是state,第二个参数是载荷

  • 在调用时:用 this.$store.commit(‘mutation名’, 载荷) 来调用

  • 注意:Mutation 必须是同步函数,Mutation 里面不能放异步代码

     mutations:{
        // 每一项都是一个函数,可以声明两个形参
        mutation名1function(state [, 载荷]) {
      	
        },
        mutation名2function(state [, 载荷]) {
      
        }
      }
    
    //在实例中调用
    this.$store.commit('mutation名', 实参)
    
5、基于辅助函数对调用方式的简化
  • 使用…mapGetters …mapState …mapActions …mapMutation

  • 这种方式相当于将store中的属性映射在组件的方法属性中

  • 我们在组件中使用this调用就行

    //在使用的时候引入vuex
    import {mapState,mapGetters,mapMutations,mapActions} from 'vuex' 
    methods: { 
      ...mapMutations(['mutation名'])
      ...mapActions(['mutation名']),
      //...mapMutations({'新名字': 'mutation名'})
    }, 
    computed:{//计算属性
           ...mapState(['数据名1','数据名2'])
    	   ...mapGetters(['方法名1'])
     },
    
    
    
6、Module 对象
  • 拆分模板,把复杂的场景按模块来拆开

  • 可以根据模块将store划分为不同的业务模块,在module对象中配置多个对象

  • 每个对象都是一个小的store

    modules: {
        模块名1{
             // namespaced为true,则在使用mutations时,就必须要加上模块名
             namespaced: true, 
             state: {},
             getters: {},
             mutations: {},
             actions: {},
             modules: {}
        },
        模块名2{
            // namespaced不写,默认为false,则在使用mutations时,不需要加模块名
             state: {},
             getters: {},
             mutations: {},
             actions: {},
             modules: {}
        }  
      }
    
    //模块中的mutations/actions:
    //namespaced为true,则需要额外去补充模块名
    //namespaced为false,则不需要额外补充模块名
    
    //加入模块后使用数据
    $store.commit('mutations名')        // namespaced为false
    $store.commit('模块名/mutations名')  // namespaced为true
    
    

7、axios请求

  1. 支持多种请求方式:

    • axios(config)
    • axios.request(config)
    • axios.get(url, [config])
    • axios.delete(url, [config])axios.head(url, [ config])
    • axios.post(url, [data, [config]])
    • axios.put(url, [data, [config]])
    • axios.patch(url, [ data, [ config]])
  2. 全局配置

    1. 开发中,很多参数是固定的. 可以进行一些抽取, 也可以利用axiox的全局配置

      npm i axios -s
      
      import axios from 'axios'
      import vue from 'vue'
      vue.use(axuos)
      const service = axios.create({ //创教axios
      	baseURL: 'http://127.0.0.1:8888/api/private/v1/',
      	timeout: 30000, //设置请求超市
      })
      
      //1. 过滤一些信息
      //2. 每次请求后, 会展示loding图标
      //3. 某些网络请求(登录的token), 必须携带某一些特殊的信息
      //请求拦截器
      service.interceptors.request.use((config) => {
      	// 在请求前做一些处理
      	const token = window.sessionStorage.getItem("token")
      	config.headers.Authorization = token //传入token
      	return config
      }, err => {
      	return Promise.reject(err)
      })
      
      //响应拦截器
      //1.判断授权是否过期
      //2.判断返回的错误直接提示
      service.interceptors.response.use(response => {
      	if (response.status == 401) {
      		MessageBox.alert('授权过期,请重新登录', {
      			confirmButtonText: '重新登录',
      			callback() {
      				location.href = '/login'
      			}
      		})
      	} else if (response.status == 400) {
      		message('请求的地址不存在或者包含不支持的参数', 'error')
      	} else if (response.status == 403) {
      		message('被禁止访问', 'error')
      	} else if (response.status == 404) {
      		message('请求的资源不存在', 'error')
      	} else if (response.status == 500) {
      		message('内部错误', 'error')
      	}
      	return response
      })
      
      export {
      	service
      }//抛出
      
  3. 封装axios

    1. get

      //方法1 传值的方式
      import {service} from '@/api/api.js'
      export function get(url, params) {
      	return new Promise((resolve, reject) => {
      		axios.get(url, {
      			params: params
      		}).then(res => {
      			resolve(res.data);
      		}).catch(err => {
      			reject(err.data)
      		})
      	})
      })
      
      
    2. post

      //方法1 传值的方式
      import {service} from '@/api/api.js'
      export function get(url, params) {
      	return new Promise((resolve, reject) => {
      		axios.post(url, {
      			params: params
      		}).then(res => {
      			resolve(res.data);
      		}).catch(err => {
      			reject(err.data)
      		})
      	})
      })
      //在创建一个api.js然后使用封装的方法二次封装具体请求,传入参数即可
      
    3. 分别封装

      //直接封装具体请求
      import {service} from '@/api/api.js'
      export function login(data) {
      	return service({
      		url: `login`,
      		method: 'post',
      		data: data,
      	})
      }
      
  4. 请求配置信息

    1. 请求地址 url: ‘/user’,
    2. 请求类型 method: ‘get’,
    3. 请根路径 baseURL: ‘http://www.mt.com/api’,
    4. 请求前的数据处理 transformRequest:[function(data){}],
    5. 请求后的数据处理 transformResponse: [function(data){}],
    6. 自定义的请求头 headers:{‘x-Requested-With’:‘XMLHttpRequest’},
    7. URL查询对象 params:{ id: 12 },
    8. 查询对象序列化函数
    9. paramsSerializer: function(params){ }
    10. request body
    11. data: { key: ‘aa’},
    12. 超时设置s timeout: 1000,
    13. 跨域是否带Token withCredentials: false,
    14. 自定义请求处理 adapter: function(resolve, reject, config){},
    15. 身份验证信息 auth: { uname: ‘’, pwd: ‘12’},
    16. 响应的数据格式 json / blob /document /arraybuffer / text / stream
    17. responseType: ‘json’,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值