vue 知识点

836 阅读10分钟

~基本知识点

0.$data,$el,$watch 都是vm(实例)所拥有的方法或者属性  可以通过$+vue实例中属性--->直接操作表达
1.obejct.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,
2. <!-- 绑定一个disabled只要值不为空 就是true -->  <li :disabled = "lop">{{res}}</li>  
3.  <button v-on:[event] ='evenFun'></button>绑定一个事件名称event(动态参数),该绑定事件类型的方法不能用@来绑定
动态绑定元素属性值 <li v-bind:[names] = 'url'></li>
对动态参数的值的约束:
动态参数预期会求出一个字符串,异常情况下值为 null。这个特殊的 null 值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。
而且动态参数值只能小写,不支持大写
<!-- 在 DOM 中使用模板时这段代码会被转换为 `v-bind:[someattr]` -->
<a v-bind:[someAttr]="value"> ... </a> 
4.
      computed:   计算属性有缓存:计算属性是基于它们的响应式依赖进行缓存的;只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
      我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
     
      <p>{{wwws}}</p> //代表返回的computed计算值
      
       computed : {
               wwws () {
                   return Date.now();
               }
            }
            
            <div>{{gets}}</div>
            默认是每个计算属性计算时有get函数,可以进行缓存
             gets: {
                   get () { // ,在数据未发生变化时,优先读取缓存
                       return this.text + this.str
                   },
                    set() { //在设置数据时触发
                       return this.text + this.str
                   }
               }
5. watch:观察和响应 Vue 实例上的数据变动:侦听属性
https://www.cnblogs.com/yesu/p/9546458.html

6.  <li v-bind:class="bd">bds</li>//绑定一个返回对象的计算属性含的class,这是一个常用且强大的模式:
bd () {  
                    return {
                        active:'active',
                        en:'en'
                    }
               }
result——><li class="active en">bds</li>

 <li v-bind:class="[on ? on1 : on2]">on</li> //据条件切换列表中的 class,可以用三元表达式
        <div v-bind:class="[{ active: isActive }, errorClass]"></div>//当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法
        
        
        
7.Vue 不能检测以下数组的变动:
        
        当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
        当你修改数组的长度时,例如:vm.items.length = newLength
        举个例子:
        
        var vm = new Vue({
        data: {
        items: ['a', 'b', 'c']
        }
        })
        vm.items[1] = 'x' // 不是响应性的
        vm.items.length = 2 // 不是响应性的


Vue 不能检测对象属性的添加或删除::::
        对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以
        使用 Vue.set(object, propertyName, value)或者vm.$set()方法向嵌套对象添加响应式属性;


        JS:Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
        Object.assign(target, ...sources);target: 目标对象 sources: 源对象
        var obj1 = {
        b:2,
        a:1
        }     
        var obj2 = {
        c:3,
        d:4
        }  Object.assign(obj1,obj2);//obj2和obj1合并
为已有对象赋值多个新属性:::::
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
});

8.想要显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据--用computed和filter返回过滤值即可

<li v-for="fa of fas">{{fa}}</li>
data () (
    return { num:[1,2,3,4] }
},
computed:{
    fa () {
        return this.num.filter(function (num) {
            return num > 3
        })
    }
}

在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法: 传参给循环对象,methods展示返回

<li v-for="n in even(mum)">{{ n }}</li>  v-for可以接受一个有参函数
methods : {
    even (num) {
        retun this.num.filter(function (num) {
            return num > 3
        })
    }
}

9.v-if 与 v-for 同时使用
当v-if与v-for处于同一级时 v-for的优先级比v-if高
这意味着 v-if 将分别重复运行于每个 v-for 循环中
当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:
<li v-for="todo in todos" v-if="!todo.isComplete">
    {{ todo }}
</li>
上面的代码将只渲染未完成的 todo。

***10: props
    传递静态或动态 Prop:

    --------静态传一个props:
    <el-html tis="你哈"></el-html>//你哈
    Vue.component('el-html',{
        props:{
            tis:{
                type:String
            }
        }
    template:'<h2>{{tis}}</h2>'
});

    ------动态传一个props:
    <el-html :tis="txt"></el-html>//ppp
    Vue.component('el-html',{
        props:{
            tis:{
                type:String
            }
        }
    template:'<h2>{{tis}}</h2>'
});
data(){
    return {
       txt:'ppp'
    }
}

------传入一个对象和数组
 <list-si 
        :name="{
            name1:'qqq',
            name2:'eee'
        }"
        age="[1,2,3]"
        ></list-si>
        
        Vue.component('list-si',{
            props:{
                name:{
                    type:Object
                }
            }
            props:['age']

            template:'<h4>{{name.name1}} {{age[0}}</h4>' //qqq 1
        });
        

  11.slot插槽用法
  slot插槽(<slot></slot>)解决了在父组件中显示子组件标签中定义的内容
  
  父组件
  <template>
    <div>父组件
       <chi :ids="1">wwwww</chi>
    </div>
</template>
<script>
import chi from './chi.vue'
    export defalut {
    components:{chi}
        
        
    }
</script>

  子组件:
 <template>
    <div>子内容
       <h2 v-if=" ids === 1">
        <slot></slot>  //定义此插槽标签为了展示父组件中的 wwwww 字段
        </h2>
    </div>
</template>
<script>
    export defalut {
        props:{
            ids: {
                type: Number,
                required: true
            }
        }
    }
</script>
slot通常结合render(渲染函数使用)
ps:单文件组件中使用render函数,需要去掉<template>
<script>
export default {
    props: {
    level: {
      type: Number,
      required: true
    }
  },
  render (ce) {
    return ce(
      "div", // 标签名称
      this.$slots.default // 子节点数组
    );
  }
} 
</script>
*12. keep-alive  是vu的内置组件  主要用于保留组件状态或避免重新渲染,这样会大大的节省性能。
他是个抽象组件,不会被渲染到真实DOM中,也不会出现在父组件链中。
*keep-alive的生命周期:
当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated
用法1:在app.vue中缓存所有组件的状态
       <keep-alive>
     <router-view/>
   </keep-alive>
 用法2:按需缓存组件,在app.vue中如下:
 <keep-alive>
  <router-view v-if="$route.meta.keepAlive" style="min-height:100%"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" style="min-height:100%"></router-view>
//不需要刷新的路由配置里面配置 meta: {keepAlive: true}, 这个路由则显示在上面标签;
//需要刷新的路由配置里面配置 meta: {keepAlive: false}, 这个路由则显示在下面标签;
在路由index.js 如下:
     {
      path: '/',
      name: 'index', 
      // 路由懒加载
      component: resolve => require(['.././components/crm/index.vue'],resolve ),//用require引入,将component分别打包成不同的js,按需加载,避免加载时间长
      // component: () => import('.././components/crm/index.vue'),
      meta: {//配置meta
        title: 'index',
        keepAlive: true
      },
      
     beforeEnter (to,from,next) {//利用transition提供的钩子函数,设置组件状态
        to.meta.keepAlive = false;
        next()
     }
    },
    在index模板中改变meta的keepAlive的状态如下:
    export defalut {
         beforeRouteEnter (to, from, next) {  //进入index模板时,不会缓存该模板内容状态
         to.meta.keepAlive = false;
         next();
      },
    }
    
    ================================================================   
    
        
        <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
    <div class="list">
        <ol>
            <to-list :item = "list" v-for="list in lists"></to-list>
            <!-- to-list是父组件,将通过bind绑定一个值item,子组件li通过props接受 -->
        </ol>  

        <div v-html="res" :title="oop + 'ppo'"></div>
        <p>{{lop + lop}}</p>
        <!-- <p>{{ ok ? 'YES' : 'NO' }}</p> -->
        <p>{{lop+str.split('')}}</p>
        <!-- <p v-if="fs">fff</p> -->
        <h3 v-on:click="fs = !fs">ffrf</h3>
        <p v-if="fs">{{shows}}</p>
        <!-- 绑定一个disabled只要值不为空 就是true -->
        <li :disabled = "lop">{{res}}</li>  

        <button v-on:[event].prevent = 'evenFun'>回值</button>
        <div :[namesAtr]="url">fff</div>

         computed:

         <p>{{wwws()}}</p> //调用方法返回值
         <p>{{wwws}}</p> //代表返回的computed计算值

         计算属性有缓存:计算属性是基于它们的响应式依赖进行缓存的;只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
         <div>{{datas}}</div>
         <div>{{datas2()}}</div>

         <div>{{js}}</div>
         <div>{{gets}}</div>

         watch:观察和响应 Vue 实例上的数据变动:侦听属性
        <!-- <div>{{ fullName }}</div> -->

        class style绑定:  
        <li class="active1" v-bind:class="{active:actives,active2:actives2}">actives</li>
        <li v-bind:class="cd">cds</li>//对象class
        <li v-bind:class="bd">bds</li>//绑定一个返回对象的计算属性含的class

        <!-- 数组绑定class -->
        <li v-bind:class="[on,on1,on2]">on1</li>
        <li v-bind:class="[on ? on1 : on2]">on</li> //据条件切换列表中的 class,可以用三元表达式
        <div v-bind:class="[{ active: isActive }, errorClass]"></div>//当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
        <!-- 绑定style -->
        <li :style="{fontSize:aco + 'px'}">嗯嗯嗯</li>
        <li :style="styles">this is fangsi</li>
        <!-- v-for索引 键 -->
        <li v-for="(ins,key,index) of inss">{{ins}} {{key}} {{index}}</li>

        Vue 不能检测以下数组的变动:
        
        当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
        当你修改数组的长度时,例如:vm.items.length = newLength
        举个例子:
        
        var vm = new Vue({
        data: {
        items: ['a', 'b', 'c']
        }
        })
        vm.items[1] = 'x' // 不是响应性的
        vm.items.length = 2 // 不是响应性的


Vue 不能检测对象属性的添加或删除::::
        对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以
        使用 Vue.set(object, propertyName, value)或者vm.$set()方法向嵌套对象添加响应式属性;


        JS:Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
        Object.assign(target, ...sources);target: 目标对象 sources: 源对象
        var obj1 = {
        b:2,
        a:1
        }
        var obj2 = {
        c:3,
        d:4
        }  Object.assign(obj1,obj2);//obj2和obj1合并
为已有对象赋值多个新属性:::::
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})


    </div>  
    <script>
        Vue.component('to-list',{
            props:['item'],
            template:'<li>{{ item.text }}</li>'   
        });
        var vm = new Vue({  
            el:'.list',  
            data () {  
                return {
                    lists:Object.freeze([ //Object.freez阻止死对象被修改,也意味着响应系统无法再追踪变化。
                        {text:'1'},
                        {text:'2'}
                    ]),
                    text:'js',
                    res:'<li>JavaScript</li>', 
                    oop:'oop',
                    lop:'lop',
                    str:'java',
                    fs:true,
                    shows:'ppp',
                    url:'a.html',
                    event:"mouseleave", 
                    namesatr:'href',
                    actives:true,
                    actives2:true,
                    //对象class
                    cd : {
                        on : true,
                        ons : true
                    },  
                // 数组class
                    on: 'true', on1: 'true2', on2: 'true3',
                    aco:2,
                    styles:{
                        fontSize:'20px',
                        color:'red',
                        disPlay:'block'
                    },
                    inss:{
                        insss:'oo',
                        www:'ww',
                        eee:'ee'
                    }
                }
            },
            computed : {
               wwws () { return this.oop.split('').reverse().join(''); },
               datas () { return Date.now(); },
               js () { return Date.now() },
               gets: {
                   get () { // 默认是每个计算属性计算时有get函数,可以进行缓存,在数据未发生变化时,优先读取缓存
                       return this.text + this.str
                   },
                    set() { //在设置时值触发
                       return this.text + this.str
                   }
               },
            //    绑定一个返回对象的计算属性含的class
               bd () { 
                    return {
                        active:'active',
                        en:'en'
                    }   
               }  
            },
            watch: {     
            },
            created () {
              console.log(this.text);
            },
            methods:{
                evenFun () {
                    alert(0);
                },
                wwws () {
                     return this.oop.split('').reverse().join('');
                },
                datas2 () {  
                    return Date.now()   
                }
            }
        });  
        console.log(vm.$el); //输出div
        // $data,$el,$watch 都是vm(实例)所拥有的方法或者属性
        vm.$data.oop = 'ui';
        vm.$data.str = 'kkk';
        vm.$set(vm.inss,'hu','pp');//使用 Vue.set(object, propertyName, value)或者vm.$set()方法向嵌套对象添加响应式属性; vm.$set是Vue.set的别名,两者功能一样
        vm.inss = Object.assign({},vm.inss,{
            k:'ee',
            l:'hh'
        });
    </script>    
</body>
</html> 

~vue-router

1//首当其冲
   Vue.use(Router);
   export defalut new Router({
       routes:[
       {
           path:'/',
           name:'first',//此模板中使用router-view标签将要用的子页面(first-child)拿来,子路由的情况一般用在一个页面有他的基础模版,然后它下面的页面都隶属于这个模版,
           component:first,
       //主页中的子路由显示项
       children:[
        {
            path:'/first-child',
            name:''
        }
       ]
           
       }
       ]
       
   })
   (2)路由传参
       @通过router-link:to绑定所需参数向lonarui4传参:
        <router-link :to="{name:'lonarui4',path:'/lonarui4',params:{name1:'哈哈'}}">go to lonarui4</router-link>  在lonarui4模板中用{{$route.params.name1}}接受即可
        
       @通过点击事件用全局$router给地址路径追加($router.push)值传参:
       <div @click="to_lonarui4"></div>
       export defalut {
           methods:{ 点击跳转传参
           to_lonarui4 () {
                                this.$router.push({
            name:'lonarui4',   用name来*识别*,保持与query一致性  或者用 path:'/lonarui4'
           params:{  //注意params有个坑————浏览器刷新会导致传的参数不存,将params换成query即可;这是由于query与params传参机制不一样,造成的差异,如果要隐藏参数用params,如果强制刷新不被清除用query。
             page:'1',
             code:'00'
      }
    })
           }
           }
       }
       
       lonarui4页面接受:
       mounted(){
               console.log(this.$route.parmas.page);
                 console.log(this.$route.query.page);
       }
   
   @通过配置路由index.js来传参
    export defalut new Router({
       route:[
           {
               path:'/lonarui4/:id/:conts', 在url中用:“:字段”  配置参数
               //path:'/lonarui4/:id(\\d+)/:conts',//加入了正则,再传递数字之外的其他参数,组件就没有办法接收到。
               name:'lonarui4',
               component:lonarui4
           }
       ]
    });
   在主模板中 <router-link to="lonarui/目标id/内容"></router-link>
   在lonarui4模板中   用{{$route.params.id}}  {{$route.params.conts}}  接收
   (3)路由中的钩子函数(导航守卫)
   beforeRouteEnter:在路由进入前的钩子函数。
   beforeRouteUpdate: 在当前路由改变,但是该组件被复用时调用
   beforeRouteLeave:在路由离开前的钩子函数。
       三个参数:
           to:路由将要跳转的路径信息,信息是包含在对像里边的。
           from:路径跳转前的路径信息,也是一个对象的形式。
           next:路由的控制参数,常用的有next(true)和next(false)。
   {
     path:'/lonarui4/:lisId/:listTit',
     name:'lonarui4',
     component:lonarui4,
     beforeEnter:(to,from,next)=>{    如果使用钩子函数,对应要跳转的lonarui4所在的router-link会失效
       console.log('我进入了lonarui4模板');
       console.log(to);
       console.log(from);
       console.log(next);
     }
   }
   (3)路由懒加载
   
  --------------------过渡---------------
   .fade-enter {
 opacity:0;
}
.fade-leave{
 opacity:1;
}
.fade-enter-active{
 transition:opacity .5s;
}
.fade-leave-active{
 opacity:0;
 transition:opacity .5s;
}
   <transition name="fade" class="fade-enter-active"> 
   <router-view></router-view> //加载子路由可设置过渡
   </transition>
   ** css过渡类名: ** 组件过渡过程中,会有四个CSS类名进行切换,这四个类名与transition的name属性有关,比如name=”fade”,会有如下四个CSS类名:

   fade-enter:进入过渡的开始状态,元素被插入时生效,只应用一帧后立刻删除。
   fade-enter-active:进入过渡的结束状态,元素被插入时就生效,在过渡过程完成后移除。
   fade-leave:离开过渡的开始状态,元素被删除时触发,只应用一帧后立刻删除。
   fade-leave-active:离开过渡的结束状态,元素被删除时生效,离开过渡完成后被删除。

-------------------配置404--------------------
{
   path:'*',  //这里的path:’*’就是找不到页面时的配置
   component:'Error'  //404页面
}
<router-link to="/b">瞎写的</router-link> 跳转找不到这个路径所示页面,启动Error页面

~Vuex:


11.------------------------------vueX------------------------------------------------
 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,
    
  这个状态自管理应用包含以下几个部分:
  state,驱动应用的数据源;
  view,以声明方式将 state 映射到视图;
  actions,响应在 view 上的用户输入导致的状态变化。  
    
  每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)
  
  Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用
    
例:
建立store.js,安装vuex
store.js::::
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {   //state存贮要公用的数据
    num:1,
    str:'qq'
}
const mutations = {  //mutations对存储的数据进行按需操作
    add (state) {
        state.num++
    },
    changStr (state) {
        console.log(state.str)
    }
    
    
    export defalut new VueX.Store{   导出全局的$store对象,以便各个模板使用
        state
    }
}

//模板中调用使用
<div>{{$store.state.num}}</div> 1
<span @click="$store.commit('add')">add+</span>  //用comit提交触发mutatons中函数
<span @click="$store.commit('changStr')">{{$store.state.str}}</span> qq
import store form '....'

1. 用computed获取store中的状态(state)值
(1)第一种方法:直接通过计算返回
computed:{
     getState () {
         return this.$store.state.num   //模板调用 <div>{{getSate}}</div>
     }
 }
 
 (2)第二种方法:通过mapState的对象来赋值
 先引入mapState  import {mapState} from 'vuex'
 computed:mapState(
    getState:state => state.num   //模板调用 <div>{{getSate}}</div>
 )
 (3)第二种方法:通过mapState的对象设置数组来获取state
  computed:mapState(["num"]),   //模板调用 <div>{{getSate}}</div>
 
 ---store.js:::
 const state = {   //state存贮要公用的数据
    num:1,
    str:'qq' 
}

*****但是呐:如果我们需要在一个computed中处理很多个数据时,那这时就不能这样写了,因为一个模板中只能有一个computed起作用,那咋办嘛,用es6的扩展运算符即可:looK!

****computed:{
    ...mapState({
        getState:state => state.num
    }),
    ...mapState(["num"])   //这样写简单明了
}


2.Mutations修改state状态
  (1)$store.commit() 通过commit提交得到state值
    <span @click="$store.commit('add',n)">add+</span>  //用comit提交触发mutatons中函数  可传值n到mutations中
   const mutations = {
    add(state,n) {
     state.num+=n
    }
}
(2)使用mapMutations修改state状态
 先引入mapMutations import { mapState,mapMutations } from 'vuex';
     methods:mapMutations(
            ['add','reduce']
        )
        
        调用 <div> @click="add">{{$store.state.num}}</div>
    
  ******同computed一样,methods也只能在模板中出现一次,所以用扩展符:
  **methods:{
   ...mapMutations('add','reduce')
  }
  
  
  3.getters计算过滤操作
  
  有这样一个需求哈:从store中取值时,首先给所需值过滤操作,怎么实现?,所以vux提供了getters这个方法用于数据的过滤操作
  
  现在我们对num预先操作下,让他每次更改值时,加10
  
  const state = {
      num:1
  }
  const getters = {
      num (state) {
        return state.num += 10  
      }
  }
  //export导出getters
  export default new Vuex.Store({
    state,mutations,getters
});

模板中调用:::
import {mapState,mapMutations,mapGetters} from 'vuex'
<p>{{num}}</p> //11
computed: {
    ...mapState(['num']),
    num () {
        return this.$store.$getters.num
    }
    //由于vux提供了mapGetters  所以像...mapState(['num'])可以用扩展符来写
    mapGetters(['num'])
    
}
4.actions异步修改状态
 actions和mutations的基本功能都一样,都是显示提交(commit)更改state状态,
 唯一不同:actions是异步来调用修改mutations中定义的数据(数据在函数中)状态,而mutations是同步来修改state中的数据状态
//上码子:

    const = state {
        num:0
    }
    //用mutations同步更改state状态
   const  mutaions = {
       add(state,n) {//传参

           state.num += n
       }
   }
   
   用actions异步提交(commit)更改mutaions中的数据;
   context:上下文对象,这里你可以理解称store本身。
   {commit}:直接把commit对象传递过来,可以让方法体逻辑和代码更清晰明了。
   const actions = {
    adds (contTxt) {
        contTxt.commit('add',10)  //调用store的commit方法提交进行更改状态
    }
    //更明了的写法
    adds ({commit}) {将store的commit方法直接以对象的形式作为形参,提供函数体调用修改mutiaons中的数据
        commit('adds',10)   
    }
   }
   
   import {mapState,mapMutations,mapGetters,mapActions} from 'vuex'
   export defalut new Vuex.Store({
       state,
       mutaions,
       getters,
       actions
   });
   //在模板中调用
   <div @click="adds">{{num}}</div>   //点击后  10
   
  export defalut {
    computed : {
        ...mapstate([num])
    },
    methods : {
        ...mapActions(['adds'])
    }
  }
  
  
  5.module(状态管理器的模块组)
  随着项目的复杂性增加, 共享的状态越来越多,这时候我们就需要把我们状态的各种操作进行一个分组,分组后再进行按组编写。
   
   const firstModlue = {
       state: {
           number:1
       },
       mutations: {
           adds (state) {
              state.number++
           }
       },
       getters: {
           number (state) {
               return state.number += 10 
           }
       },
       actions: {
           addsActions ({commit}) {
            commit('adds')
           }
       }
   }
    export defalut new Vuex.Store({
       modules: {
            first:firstModlue
       }
    });
    //模板中调用
    
    <div>{{$store.state.first.number}}</div>  //调用modules中的first状态组
    <div>{{number}}</div>
    
    computed: {
        ...mapState({
            number: state => this.$store.state.first.number  
        })
    }
  

~vue axios

为什么选择axios?
~使用axios可以统一做请求-响应拦截,例如响应时我们将响应信息拦截起来,判断状态码,从而弹出报错信息
~设定请求超时,例如3000ms未响应则停止请求
~基于promise,可以很方便地使用then或者catch来处理请求
~自动转换json数据 Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中;

它有以下特性:
~在浏览器中创建 XMLHttpRequests
~在 node.js 则创建 http 请求
~支持 Promise API
~支持拦截请求和响应
~转换请求和响应数据
~取消请求
~自动转换 JSON 数据
3 ~客户端支持防御 XSRF

1.在main.js导入:

import axios from 'axios'
//将axios赋值到原型上:
Vue.prototype.$ajax = axios

2.模板中码子展示:

<style>
  img {width: 30px;}
</style>
<template>

  <div>
    <ul>
      <li v-for="(list,index) of lists" :key="list.id">
        <span>{{list.id}}</span>
        <i>{{list.name}}</i>
        <em>{{list.des}}</em>
      </li>
      <hr>
      <ul>
        <li v-for="good of goods">
        <span>{{good.t1}}</span>
        <span><img :src="good.t2"></span>
        <span>{{good.t3}}</span>
        </li>
      </ul>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      lists:[],
      goods:[],
      URL:{
        url1:"http://www.wujiaweb.com/api",
      },
      getAxios() {
      
      调用全局$ajax
        this.$ajax
          .get(this.URL.url1, { id: 1, name: "r" })
          .then(res => {
            let resResult = res.data.data;
            console.log(resResult);
            let _this = this;
            resResult.favourite_goods.forEach((val) => {
              _this.lists.push({
                id: val.goods_id,
                name: val.goods_name,
                des: val.goods_remark
              });
            });
             resResult.hot_goods.forEach((val) => {
               console.log(val);
               _this.goods.push(
                 {
                   t1:val.goods_sn,
                   t2:_this.URL.url1.substr(0,23) + val.original_img,
                   t3:val.goods_name
                 }
               )
             })
          },(error) => {
            console.log(error);
          }).catch(res => {
            console.log(res);
          });
      }
    };
  },
  mounted() {
    let _this = this;
    this.$nextTick(() => {
      getUser();
      async function getUser() {
        try {
          const response = await _this.getAxios();
          console.log(response);
        } catch (error) {
          console.error(error);
        }
      }
    });
  }
};
</script>

如果一次性要请求多个接口呢(执行多个并发请求):
处理并发请求的助手函数:

axios.all(iterable)
axios.spread(callback)

如下使用:

mounted () {
let _this = this;
     function get1() {
      return _this.$ajax.get("http://www.wujiaweb.com/api/goods/advertise");
    }
    function get2() {
      return _this.$ajax.get("http://www.wujiaweb.com/api/goods/category");
    }
    function get3() {
      return _this.$ajax.get("http://www.wujiaweb.com/api/cart");
    }
    _this.$ajax.all(
    [get1,get2,get3]
    ).then(
     _this.$ajax.spred(data1,data2,data3) { //通过sperd得到all中请求的接口,  data1等代表$ajax.all中的get
      let a = data1.data.data.filter(val => {  
          return val.ad_id > 70;
        });
        console.log(a);  
    }
    )
}

请求方法的别名
为方便使用,官方为所有支持的请求方法提供了别名,可以直接使用别名来发起请求:

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]])

在使用别名方法时, url、method、data 这些属性都不必在配置中指定。

一般在我们实际项目中,都会封装一个全局的axios用于远程数据拉去,
为什么要封装?
封装有助于全局使用,设置统一的请求拦截,有助于维护
来吧,码子展示

1.首先建立http.js文件
2.引入axios和qs,
3.设置拦截器,
4.按需设置要用的请求方法

import axios from 'axios'
import qs from 'qs'//序列化字符串,处理发送请求的参数  axios发送的数据不是json格式,若需要json格式,添加此库
axios.interceptors.response.use(response => { // 对响应数据做点什么
  return response.data
}, function (error) {
  console.log(error);
});
axios.interceptors.request.use(config => { // 对响应错误做点什么
  return config;
}, function (error) {
  return Promise.reject(error)
});

export default {
  // 全局token
  get(url, params) {
    return axios({
      method: 'get',
      url: url,
      params,
      withCredentials: true,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
      }
    })
  },
  post(url, data) {
    return axios({
      method: 'post',
      url: url,
      data: qs.stringify(data),
      withCredentials: true,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
      }
    })
  },
  form(url, formdata) {
    return axios({
      method: 'post',
      url: url,
      data: formdata,
      withCredentials: true,
    })
  },
  getJson(url) {
    return axios({
      method: 'get', 
      url: url
    })
  }
}

5.在main.js 入口文件中引入http.js

import http from  './assets/js/http'

6.模板中调用使用

mounted () {
    this.$http.post(
      'http://www.xuefu.com/data/student',
      {
          name:'_'
      }
    ).then(res => {
        console.log(res);
    }).catch(res => {})
}

~vue原理剖析

vue调用顺序: index.html → main.js → app.vue → index.js → components/组件 先来个图看下整个vue-cli初始项目的流程 ![](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/11/19/16e819fac1b7b140~tplv-t2oaga2asx-image.image) 1.vue-cli会先判断你的模板在远程github仓库上还是在你的本地某个文件里面,若是本地文件夹则会立即跳到第3步,反之则走第2步。
2.第2步会判断是否为官方模板,官方模板则会从官方github仓库中下载模板到本地的默认仓库下,即根目录下.vue-templates文件夹下。
3.第3步则读取模板目录下meta.js或者meta.json文件,根据里面的内容会询问开发者,根据开发者的回答,确定一些修改。
4.根据模板内容以及开发者的回答,渲染出项目结构并生成到指定目录。 https://www.jianshu.com/p/fd00e25ff146 https://www.cnblogs.com/bgwhite/p/9578258.html

~vue面试题走你

https://mp.weixin.qq.com/s/7XOcnqDX4e3MWU9UY1bh3A