vue2知识点

 
   初学vue  
   模板语法(2大类)
1.插值语法 
 	     2.指令语法 
   数据绑定  
                1.单项数据绑定 
                2.双向数据绑定
   el和data的两种写法  
    MVVM 模型 
   Object.defineProperty(obj,'key' ,{}) 重要 
     数据代理 
  vue中的数据代理  
  事件的基本使用 
  VUE的事件修饰符 
   键盘事件
   计算属性  (computed) (简单记就是把data中的属性拿过来加工)
     watch属性  监视属性  
class绑定  
style 绑定  
条件渲染   v-show 和 v-if
 列表渲染 
key的原理  
列表过滤
列表排序
监测数据的原理     对象
set 的使用  (适用于data中某一个对象中没有对应的属性 , 但后续需要手动添加)
set 也可用在数组中 
v-model在表单数据中的使用   
过滤器
Vue中的事件修饰符 
 自定义指令 
生命周期
组件的优点    组件的定义  ------ 实现应用中 局部功能代码和资源的集合 
Vue组件编程化 
为啥组件中data形式  用函数 不会用对象形式  
非单文件组件 
关于vueComponent
原型的复习  
Main.js中的render函数
修改默认配置 
ref  的使用 
props  其中不能传key这个关键字 
mixin 混入  
插件 
scoped 
如何将数据保存到本地存储  仅供参考   通过监视属性  watch  来实现
组件自定义事件  
备注第二种方法 更加灵活  
全局事件中线
消息订阅与发布 
$nextTick   
总结动画与过渡    
      vue脚手架配置代理
Vue-resource的使用 
插槽 
Vuex的原理图  
Vue中搭建
Vuex中的map方法 
Vuex模块化 
   Route几个注意点
     路由的query参数 
命名路由
路由的params参数 
路由使用props配置 
<router-link>的replace属性 



   初学vue  
                   
  el  (是element的简称) 用于指定当前vue实列为那个容器服务,值通常是为css选择器字符串      不仅仅只有 el : “#root”  ,  el : ".root" 	, el :"div"  ,   还有一种不常见的写法  el : document.getElementById("root")   
  data中的用于存储数据 , 数据供el 所指定的容器 去使用 值可以是一个对象  一个函数  
  root 容器 里面的代码 依然符合 html规范 , 只不过混入了一些特殊的vue 语法  root容器里面的代码 被称为 【vue模板】
  插值语法 {{ 1 + 1 }}  ,{{Date.now()}} ,{{name}}  {{}}里面可以写 js表达式   也可以写vue实列化对象上的属性 以及vue原型上所有属性
  js表达式 : 是一种特殊的js 语句  它可以产生一个值  , 可以放在任何一个需要的地方  
  列如 a   ,   a+ b   , demo (1)  , x === y ? 'a' +'b'  
  js代码(语句)  列如  if() {}   for(){}
注意点  : vue  实列和容器是一一对应的    真实开发中只有一个vue实列  并且会配合组件一起使用    一旦data 中的数据发生改变  那么模板中用到该数据的该地方  会自动更型  
   模板语法(2大类)
1.插值语法 
  		       功能 :用于解析标签题内容
 		       写法 :{{xxx}} xxx是js表达式  且可以直接读取data 所有的属性 
 	     2.指令语法 
                        功能 :用于解析标签 (包含 :标签体内容 绑定事件 , 标签属性 ........)
                         举例  :  v-bind : ( 简写是 :)  v-bind:href="url"   可以简写为    :href="url"     
                备注 :vue中有很多指令 且形式都是v-??? , 此处我们只拿v-bind举例 

              
   数据绑定  
1.单项数据绑定 
         v-bind   :单向数据只能从data 流向页面
2.双向数据绑定
         v-model 只能应用在表达类元素/输入类元素   双向数据绑定 不仅能从data流向页面  还可以从页面流向data 
         v-model :value="aaa" 可以简写 为 v-model="aaa" 
   el和data的两种写法  
1).第一种写法  el:"#root" ;
2) 第二种写法  v.$mount("#root")   $mount() 是vue实列化对象身上的一个方法  mount英文意思是指 挂载    这种写法更加灵活 
1)第一种写法 data:{name :'xxx'} 
2)第二种写法 data(){ return{ name : 'xxx' }}     不要写成箭头函数  组件必须要用函数式   
    MVVM 模型 
                  M :模型(model) :对应的是data 中的数据
                  V :视图 (view) 模板 
                  VM :视图模型(ViewModel) vue实列对象  

   Object.defineProperty(obj,'key' ,{}) 重要 
                 它可以为对象里面添加属性  且可以控制这个属性在对象里面是否可以枚举(遍历)    是否可以删除  是否可以修改   里面还要getter 和setter 可以监听  !!! 
                 value : “值”               是要添加属性的值  
   enumerable :true     是指 控制值属性是否可以枚举  默认只是false 
   writable :true         控制是否可以被修改  默认值是false 
   configurable : true    控制属性是否被删除  默认值是 false 
   get() {}  是指 当有人读取key属性时   get函数(getter)就会被调用  ,且返回值就是 key 的值 
    set(val) {}  当有人修key属性时 ,set函数(setter) 就会被调用   且返回值就是要修改的值    
 
        // 创建一个对象 
        //先准备一个数值
        let number = 18;
        let person = {
            name: '常文俊',
            sex: '男',
            // age :'19'  //这个方式是不支持枚举的
            // age : number 
        }
        // 这种方法可以枚举 (枚举是不会参与对象遍历) 这个方式 不能直接修改和 删除  , 枚举  通过方法来实现这些功能
        Object.defineProperty(person, 'age', {
            // value : 19 ,
            // enumerable : true , //enumerable 是控制属性是否可以枚举  默认值是false
            // writable : true ,  //writable 是控制属性可以修改  默认值是false ,
            // configurable : true  //控制属性是否可以被删除  默认值false 
            //当有人读取person 的age 属性时 get 函数(getter) 就会调用  返回值是age 的值 
            // get:function(){
            //     console.log('有人读取age属性');
            //     return number
            // } ,
            //简写  
            get() {
                console.log('有人读取age属性');
                return number
            },
            //当有人修改了age 属性  则会调用这个set(setter)函数 就会被调用  且会受到修改具体的值
            set(value) {
                console.log('有人修改了age属性,且值是' , value);
                number = value ;
            }
        })
        console.log(Object.keys(person)); // Object.keys()这个方法是指 遍历里面的对象并且 把它放到数组里
        console.log(person);例  :
         


     数据代理 
                 原理  :数据代理 通过一个对象 对另一个对象中属性操作  
      //最简单的数据 代理
        let obj1 = { x: 100 }
        let obj2 = { y: 200 }
        Object.defineProperties(obj2, 'x', { 
            get() { 
                return obj1.x
            },
            set(value) {
                obj1.x = value;
            }
        })   

  vue中的数据代理  
                原理 :  通过Object.defineProperty() 这个方法   把data对象中的属性来交给vue 实列化对象身上进行数据代理   	其中data  ===  _data   但是vue._data 中的数据会进行数据劫持   
               所以只要修改vue中的属性 就可 引起data 中的 属性的改变 

  事件的基本使用 
                1. 使用v-on:xxx 或 @xxx 绑定事件 其中xxx 是事件名 
                 2. 事件的回调需要配置methods 对象中 最终会在vm上 
                 3. methods 中配置函数  不要用箭头函数 否则this 就不是vm了 
                 4. methos 中配置的函数 都是被vue所管理的函数 this的指向是vm  或 组价实列对象 
                 5。 @click=“demo($event)” 可以保留 event事件对象       

  VUE的事件修饰符 
                1.prevent   是指阻止默认事件  (常用) 
                2.stop   是指阻止冒泡 (常用) 
                3. once 是指只会触发一次事件 (常用) 
               4. capture  是指使用事件捕获模式 
               5. self   是指只有在event.target  元素身上 才会触发事件  (列如 触摸子盒子 不会 触发事件   只有触摸到父盒子 才会触发事件)
               6. passive  是指 的默认行为立即执行 无需等待事件回调执行 完毕

   键盘事件
               1. enter 回车键 
               2. delete 删除键  
               3.退出 esc
               4.空格 space 
               5.tab  换行 (特殊  ,必须配合keydown使用)    
               6. 上 up  下 down  左 left   右 right 
            vue未提供别名的按键 可以使用键盘原始的key值去绑定  但要注意转化为kebab-case (短横线命名) 
           系统修饰键(用法特殊) :ctrl alt shift  meta 
                   (1) 配合keyup使用  按下修饰键的同时  再按下其他键  随后释放其他键  事件才会被触发 
                   (2) 配合keydown使用 正常触发事件 
            也可以使用keycode 去指定具体的按键  (不推荐)
             Vue.config.keyCodes.自定义键名  =  键码  可以去定制按键比别名    
    
   计算属性  (computed) (简单记就是把data中的属性拿过来加工)
           computed会走缓存  methdos不会走缓存   
           get有啥作用 ?当有人读取时候  get 就会被调用  且get返回值就是 你所要的值
           get 啥时候被调用  ?  1.初次读取时候 2.所依赖数据发生变化的时候  
            
           如果 你计算的东西只用d读 就不用设置set 
           set 什么时候调用?当所定义的对象的值被修改时 
           set(value){
console.log('set' ,value)
   }
         
          总结 : 计算属性 : 
                       1.定义:要用的属性不从在 ,要通过已有的属性 计算得来
                       2.原理 : 底层借助了object.defineproperty 方法提供的getter 和setter 
                       3.get函数什么时候执行 ?
                                (1) 初次读取的时候会被调用 
                                  (2 ) 当依赖的数据发生改变的时候就会被调用 
                       4.优势 :与methdos实现相比 内部有缓存机制(复用) 效率更高 调试方便
                       5.备注 
                            1计算属性最终会出现在vm上,直接读取使用即可 
                             2.如果计算属性要被修改 , 那必须写set函数去响应修改 且set中要引起依赖的数据发生改变
 Vue.config.productionTip = false  ; //阻止vue 在启动时生成生产的提示
        const vm = new Vue({
            el :'.cwj' ,
            data () {
                return {
                    fisrtName : '常' ,
                    lastName : '文俊' 
                }
            } ,
            computed : {
                //完整写法 
                // fullName : {
                //     //当有人初次读取fullName 时 才会调用  get    且这个get的返回值时fullName 的值
                //     get () {
                //         return this.fisrtName + '-' + this.lastName ;
                //     } ,
                //     //只要有人修改了fullName 的时候才会调用 这个函数
                //     set(value) {
                //         //先将参数转化数组
                //         const ARR = value.split('-')
                //         this.fisrtName = ARR[0]
                //         this.fisrtName = ARR[1]
                //     }
                // }
                //简写  前提  只获取fullName 的值 不对其进行修改才会可以使用 
                  // 把fullName这个对象可以换成函数用 并且这个函数会被当成getter 用
                  fullName() {
                    return this.fisrtName + '-' + this.lastName ; 
                  }
            } 
        })

     watch属性  监视属性  
 watch :{
       isHot :{
             deep :true ,  默认的是false (深度监视) 
             immediate:true , //初始化让handler调用一次
             //handler什么时候调用? 当isHot发生改变的时
             handler(newValue , oldValue) {
                   console.log('isHot被修改了' , newValue,oldValue)
              } 
         }
 }

    总结 : 监视属性 watch 
            1.当被监视的属性改变时 ,回调函数 自动调用 进行相关的操作 
            2.监视的属性必须从在 才能进行监视
            3.监视的两种写法 

                 1)new Vue时 传入watch配置 
                 2)通过vm.$watch 监视  
     
    监视多级结构中的某个属性的变化 
    "number.a" :{
        handler() {
            console.log('a改变了')        
        }    
    }
  深度监视    
       deep :true ,  默认的是false (深度监视) 

   监视属性简写 
    (简写不能使用其中的immediate 和 deep)
            // 这是完整的
            // watch : {
            //     isHot : {
            //         deep : true ,  // 是否开启深度监视 默认值是false
            //         immediate : true ,  //这是让handler在没监视前调用  默认值是false
            //         handler (newValue , oldValue) {
            //             console.log('isHot改变了' ,newValue , oldValue);
            //         }
            //     }
            // }
            //这是简写的 前提时至有 一个handler 时候才能使用
            watch : {
                isHot (newValue , oldValue) {
                    console.log('isHot改变了' ,newValue , oldValue);
                }
            }

watch 和 computed  的区别  
1.computed 能完成的功能 watch都可以完成 
2.watch能完成的功能 computed 不一定能完成  列如 watch 可以异步处理操作 
 两个重要的原则 
 1.所被vue所管理的函数 (定时器的回调函数,ajax的回调函数等,Promise的回调函数) 最好写成箭头函数   
   这样this 指向就是vm 或组件的实列化对象 

class绑定  
  1.class样式 
       写法  :class="xxx" xxx 可以是字符串 数组 对象 
         字符串的写法 类名不确定  要动态获取 
         数组的写法  绑定多个样式  个数确定  名字也确定  但是个数不确定 
         对象的写法 绑定多个样式 个数不确定 名字也不确定 
 -----------------------------------------------------------------------------------------------------------
          <!-- 绑定class样式 -- 字符串的写法  适用于 样式类名 不确定  需要动态添加指定 -->
        <div class="cwj-str" :class="changeStr"  @click="changeClassStr">{{str}}</div>
        <!-- 绑定class样式----数组写法 适用于 需要绑定的样式个数不确定  名字也不确定 -->
        <div class="cwj-arr" :class="changeArr" @click="changeClassArr">{{arr}}</div>
        <!-- 绑定class 样式  对象的写法 适用于  要绑定的样式个数确定  样式也确定  但是动态决定用不用  -->
        <div class="cwj-obj" :class="changeObj" @click="changeClassObj">{{obj}}</div>
style 绑定  
  2.style 样式 
      :style= "{fontSize : xxx}" 其中xxx 是动态值
      :style = "a,b"其中a ,b 是样式对象  -->
      
        <!-- 绑定style样式  -->  
        <!-- 绑定style样式对象的写法  -->
        <div class="cwj-style" :style="changeStyleObj">{{style}}</div>
        <!-- 绑定style样式的数组写法  -->
        <div class="cwj-style" :style="changeStyleArr">{{style}}</div>
        <!-- 这样也是数组写法  -->
        <div class="cwj-style" :style="[c1 ,c2]">{{style}}</div>

总结 
 1.class 样式  
      写法 : :class='xxx'    xxx 可以是字符串  对象  数组 
      字符串写法适用于 类名不确定  要动态获取 
      对象写法适用于 要绑定多个样式 个数不确定  名字 不确定    
     数组写法 使用于 要绑定多个样式  个数确定 名字 也确定 但不确定用不用 
2.style样式 
  :style = '{fontSize:xxx}' 其中 xxx 是动态值 
  :style=‘{a,b}’ 其中a,b 的样式对象 


条件渲染   v-show 和 v-if
 v-show 适用于 频率高的   控制display: none 和 block 
 v-if 适用于 频率低的   控制节点是否存在  

v-if  , v-if-else , v-else    的中间不能有其他代码    

template 是模板的意思   在vue  中是不会影响排版 

总结
 1.v-if  写法 
           (1) v-if 表达式 
             (2) v-else-if = '表达式' 
             (3) v-else = ‘表达式’ 
     适用于: 切换频率较低的场景 
      特点 不展示dom 元素 直接被移除 
注意 v-if 可以 和v-else-if v-else 一起使用  但要求结构不能被 “打断” 
2.v-show  
       写法:v-show = “表达式” 
  适用于 :切换频率高的场景 
   特点 :使用v-if的时 元素可能无法获取时 而是用v-show 一定可以获取到

 列表渲染 
  v-for指令 
        1.用于展示列表数据 
        2.语法v-for="(item ,index) in xxx" :key="yyy"
        3. 遍历 数组 对象 字符串 指定次数 

key的原理  
作用是 标签的唯一标识 
 面试题 react vue 中的key 有啥作用? <key的内部原理>
   1.虚拟dom中的key 的作用 :  
            key 是虚拟dom对象的标识  当数据发生变化时 vue会根据 【新生成的数据】生成【新的虚拟dom】
            随后vue进行【新虚拟dom】与【旧的虚拟dom】 的差异比较 比较规则如下 
   2.对比规则  
            (1)旧虚拟dom中未找到新的虚拟dom 相同的key 
                         1若虚拟dom中内容没有变化 直接使用之前的真实dom 
                         2.若虚拟dom中内容变了 则生成新的真实dom 随后替换掉页面中之前的真实dom 
            (2)旧虚拟dom中未找到新的虚拟dom相同的key 
                         创建新的真实dom 随后渲染到页面 
   3.用index作为key 会引发的问题 
               1. 若对象进行: 逆序添加 或逆序删除的 等破坏顺寻的操作 
                          会产生没有必要的真实dom更新 ==》 界面效果没有问题 但效率发低 
               2.如果结构中还包含输入类的dom 
                          会产生错的dom更新 ==》界面有问题
   4.开发中如果选样key?
               1.最好使用每条数据的唯一标识 作为key 比如 id 手机号  身份证号 学号等唯一值
               2.如果不从在对数据逆序添加 逆序删除 破坏顺序操作 仅用于渲染列表展示  
                            使用index作为key是没有问题的                      


列表过滤
    <script>
        // 用watch 实现 
        //#region 
        /* new Vue({
           el : '.cwj' ,
           data() {
             return {
                 val : '' ,
                 persons : [
                     {id : '01' , name : '马冬梅' , age : 19 , sex : '女'} ,
                     {id : '02' , name : '周冬雨' , age : 20 , sex : '女'} ,
                     {id : '03' , name : '周杰伦' , age : 19 , sex : '男'} ,
                     {id : '04' , name : '伦伦论' , age : 19 , sex : '男'} ,
             ] ,
             filPersons : [] 
             }
           },
           watch : {
              val : {
                 immediate : true ,  //这个一定要写在hander的上面 
                 handler (value) { 
                     // 用一个数组来接受过滤好的数组 
                     this.filPersons = this.persons.filter((p)=>{      
                         return p.name.indexOf(value) !== -1 
                     })
                 }
              }
           }
         })
         */
        //#endregion
        //用computed实现
        new Vue({
            el: '.cwj',
            data() {
                return {
                    val : '' ,
                    persons: [
                        { id: '01', name: '马冬梅', age: 19, sex: '女' },
                        { id: '02', name: '周冬雨', age: 20, sex: '女' },
                        { id: '03', name: '周杰伦', age: 19, sex: '男' },
                        { id: '04', name: '伦伦论', age: 19, sex: '男' },
                    ],
                }
            },
            computed : {
                filPersons(){
                    return this.persons.filter((p)=>{
                        return p.name.indexOf(this.val) !== -1 ;
                    })
                }
            }
        })
    </script>


列表排序
<script>
        new Vue({
            el : '.cwj' ,
            data() {
                return {
                    val : '',
                    type : 0 , //0 是回到原来   1 是升序  2 是降序
                    persons : [
                       {id : '01' , name : '马冬梅' , age : 19 , sex : '女'},
                       {id : '02' , name : '周冬雨' , age : 20 , sex : '女'},
                       {id : '03' , name : '周杰龙' , age : 30 , sex : '男'},
                       {id : '04' , name : '龙龙龙' , age : 9 , sex : '男'}
                    ]
                }
            },
            computed : {
                filterPersons () {
                    //过滤 
                    const arr = this.persons.filter((p)=>{
                        return p.name.indexOf(this.val)   !== -1  ;
                    })
                    if(this.type){
                        arr.sort((p1, p2)=>{
                            return  this.type === 1 ? p2.age - p1.age : p1.age - p2.age
                        })
                    }
                    return arr
                }
            }
        })
    </script>

监测数据的原理     对象




内置指令 
    指令:
        v-bind:单向绑定解析表达式,可简写为:XXX
        v-model:双向数据绑定
        v-for:遍历数组/对象/字符串
        v-on:绑定事件监听,可简写为@
        v-if:条件渲染(动态控制节点是否存存在)
        v-else:条件渲染(动态控制节点是否存存在)
        v-show:条件渲染(动态控制节点是否展示)
v-text指令:
            1.作用:向其所在的节点中渲染文本内容
            2.与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会
v-html指令:
                    1.作用:向指定节点中渲染包含html结构的内容。
                    2.与插值语法的区别:
                        (1).v-html会替换掉节点中所有的内容,{{xx}}则不会。
                        (2).v-html可以识别html结构。
                    3.严重注意: v-html有安全性问题!!!!
                        (1),在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
                        (2),一定要在可信的内容上使用v-html, 永不要用在用户提交的内容上!
v-clock指令(没有值):
            1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-clock属性
            2.使用css配合v-clock可以解决网速慢时,页面展示出{{name}}的问题
v-once指令:
            1.v-once所在节点在初次动态渲染后,就视为静态内容了。
            2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
v-pre指令:
            1.跳过其所在节点的编译过程
            2.可利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译
set 的使用  (适用于data中某一个对象中没有对应的属性 , 但后续需要手动添加)
语法   注意  不能在data 中添加   必须是data 里面的属性 
vm.$set(vm.school , 'name‘  ,'清华' )   //在vue的实列化对象vm 身上使用    
   第一个参数是指  要放的位置   第二个参数是指  要添加的属性名   第三个参数是指 要添加的属性值 
Vue.set(this.school,'name' , '北大')
   第一个参数是指  要放的位置   第二个参数是指  要添加的属性名   第三个参数是指 要添加的属性值 
set 也可用在数组中 
vm.$set(vm.arr , 0  ,'清华' )  第一个参数是指 要修改的数组 第二个参数是指要修改元素的下标  第三个参数是指 修改后的内容 
 Vue.set(vm.school.arr,0,'asdf')  第一个参数是指 要修改的数组 第二个参数是指要修改元素的下标  第三个参数是指 修改后的内容 

总结 
     如果检测对象中 的数据 ?
              通过setter 实现监视  且要在new Vue 时读取传入要检测的数据 
                         (1) 对象中后追加的属性 , Vue默认不做响应式处理  
                         (2)如需给后添加的属性做响应式  请使用set 或 $set 
     如果检测数组中的数据?
               通过包裹数组里面更新元素的方法实现 本质就是做了两件事 
                     (1)调用原生对应的方法对数组进行更新 
                     (2)重新解析模板 进而更新页面 
在vue修改数组中的某一个元素 一定要借助如下方法
                    (1)使用这些API push() shift()   unshift() splice() sort() reverse()
                       (2)Vue.set()或vm.$set() 
        特别注意 Vue.set() 和 vm.$set()  不能给vm 或vm 的根数据对象 添加属性 

v-model在表单数据中的使用   
           收集表单数据  
              

       
过滤器
  定义 :对象显示的数据进行特定格式化后在显示,(适用于一些简单的逻辑的处理)
 语法 :1.注册的过滤器 :Vue.filter(name,callback) 或 new Vue(filter:{}) 
             2.使用过滤器:{{xxx | 过滤器名}} 或 v-bind :属性 =“xxx | 过滤器名”
  备注 :
         1.过滤器也可以接受额外参数 , 多个过滤器也可以串联 
         2.并没有改变原本的数据,是产生对应的数据
 
局部过滤器 

全局过滤器 


v-bind 也能使用过滤器



Vue中的事件修饰符 
     1.prevent:阻止默认事件 (常用)
     2.once 事件只触发一次 
     3.stop 阻止事件冒泡(常用)
      4.capture 使用事件的捕获模式 
     5.self :只有event.target 是当前操作的元素时才触发事件
     6.passive :事件默认行为立即执行,无需等待事件回调执行完毕

 自定义指令 
 directives 是指令的意思   
  <span b-big="data中的属性名"></span>  
 自定义指令不需要返回值   他是直接控制标签innerHTML 或 innerText  来渲染页面的

 自定义指令函数式    切记 : 1当指令绑定时候调用一次  2当自定义指令的模板进行重新解析的时候会再次调用 
    directives: {    
     /*   方式1  : 可以写成对象的形式  优势是可以处理细节的东西 
                  big :{k :v , k:v}  */
                /*   方式二 : 可以写成函数的形式 优势写起来简单 缺点就是不能处理细节上的问题 */
                /*   big 函数何时会调用函数 ? 1. 指令与元素成功绑定时(一上来) 2. 指令语法所在的模板被重新解析时  */
                big(element, binding) {
                    console.log(element);  //第一个参数指的是  真实demo
                    console.log(binding); //第二个参数指的是  值是一个对象  
                    element.innerHTML = binding.value * 10
                },
                /*        fbind(element,binding) {  
                           //用函数这样写 有细节问题  这样写一上来不会让input 框得到焦点  因为函数写法只是做了绑定和解析
                           element.value = binding.value ;
                           element.focus() ;
       
                       } */
           }
自定指令的对象式  里面有三个钩子  bind(){}    inserted(){}   update(){}   都可以接收到两个参数  分别是 element  binding 
     /*  不过对象的形式可是实现  */
                fbind:{
                    /* bind 指的是指令与元素绑定成功的时触发  */ 
                    bind(element, binding) {
                        element.value = binding.value ;
                       
                    },
                    /* 指的是所在元素被插入页面时  */
                    inserted(element, binding){
                        element.focus() ;
                    } ,
                   /*  指令所在的模板被重新解析的时 */
                    update(element, binding){
                        element.value = binding.value ;
                        element.focus() ;
                    }
                }

注意   在自定义指令里面的this 指向的不是vue的实列化对象和组件  而是window 
1. bind 是指 当自定义指令与标签绑定时候 调用 这个时候  元素还没有插入到页面   所以有些操纵是执行不了的 
2.inserted 是指 元素被插入页面的时候调用   这个时候 可以执行一些bind 操作不了的 操作
3.update 是指 当指令所在的页面发生重新渲染的时候   调用   和bind 几乎进行一样的操作 

注册全局自定指令
  //对象全局要这样写
        /*   Vue.directive('fbind' ,{
                      //bind 指的是与元素成功绑定事件 调用
                      bind (element ,binding) {
                          // console.log(element);
                          element.value = binding.value 
                      } ,
                      // inserted 指令所有元素被插值页面时调用 
                      inserted (element ,binding) {
                          element.focus()
                      } ,
                      // upodate 指的是所在模板被重新解析时调用 
                      update(element ,binding) {
                          element.value = binding.value 
                          element.focus()
                      }
                      
                  } ) */
        //函数全局这样写 
        /*        Vue.directives ('big' ,function(element ,binding) { //这里有两个参数  第一个参数指的是  给绑定的实例化对象 第二个参数指的是看控制台吧
                           // console.log(element ,binding);
                           element.innerHTML = binding.value  * 10 
                       } ,
       
                       'big-number' (element ,binding){
                           element.innerHTML = binding.value  * 10 
                       })
       
        */


自定义指令的总结 
    <!-- 总结  -->
    <!-- 需求1 : 定义一个v-big 指令 和 v-text 功能类似  但是会把绑定的数值放大10倍
    需求2 : 定义一个v-fbind 的指令 和v-bind 功能类似  但是可以让其绑定的input 元素默认获取焦点  -->
<!-- 
    自定义指令总结
       一 定义语法
        (1) 局部指令
              new Vue ({
              directives: {指令名:配置对象}
           })
          或者
          new Vue({
               directives: {指令名:回调函数}
          })
        
        (2) 全部指令 
           vue.directives (指令名,配置对象) 或者 Vue.directives(指令名,回调函数)
    
      二 配置对象中常用的3个回调
         (1)bind()  指令与元素成功绑定时调用
         (2)inserted() 指令插入页面是调用
         (3)update () 指令所在的模板被重新解析的时调用
    
      三 备注
         1.指令定义时不加v- 但是调用时要加v- 
         2.指令名如果是多个单词 要使用kebab-case 命名方式  不要用 cameClass 的方式 -->

生命周期
    <script>
        new Vue({
            el: '.cwj',
            data() {
                return {
                    n: 1
                }
            },
            /* 这个template 是模板的意思 用它的时候会把 .cwj 这个模板替换掉   里面必须有一个盒子来包其他 */
            /*      template: `<div>  <h2>当前的n值是{{n}}</h2>
             <button @click="add">点击让n+1</button></div>`, */
            methods: {
                add() {
                    console.log("add"); //假如这个vm 被销毁但是 点击事件还是有的 但是里面的n不再变化
                    this.n++
                }
                ,
                bye() {
                    console.log("bye"); //销毁了 但是点击事件还是有的 
                    this.$destroy()
                }
            },
           /*  创建vm阶段 生命周期函数    */
            /* 代表初始化 : 生命周期 事件 但数据代理还没有开始 (这个时候 无法通过vm 访问到data中的数据  mthods中的方法 ) */
            beforeCreate() {
                console.log("beforeCreate");
                // console.log(this);   /* 这里面的this指定的是vm */
                // debugger 
            },
            /*代表初始化 : 数据监测 数据代理  (这个时候  此时可以通过vm访问的data 中的数据  methods 中的配置的方法  )*/
            created() {
                console.log("created");
                // console.log(this);  
                // debugger 
            },
            /* 
                        以上这些阶段执行完成以后  vue开始解析模板  生成虚拟dom 放入 内存中  页面还不能显示解析好的内容  */
                        
            /*   挂彩的阶段 生命周期函数  */
            /*  此时页面 1.呈现的是未经vue编译的dom结构  2.所有对dom操作 最终都不奏效 */
            beforeMount() {
                console.log("beforeMount");
                // console.log(this);
                // debugger
            }, /* 这个阶段生命周期 结束以后   vm将虚拟dom转化为真实dom插入页面 */
            /*             此时
                          1.页面呈现的是经Vue编译的dom结构 
                          2.对dom操作 均有效 (尽可能避免) 至此初始化过程结束  一般在此进行 开启定时器 发送网络请求 订阅消息 绑定自定义事件  等初始化操作 */
            mounted() {
                console.log("mounted");
                console.log("mounted", this.$el instanceof HTMLElement); // 返回的是true 
                //  console.log(this);
                //  debugger
            },
            /*    更新 阶段的生命周期函数  */
            /*    此时 数据是新的 但是页面是旧的 即 页面尚未和数据保持同步  */
            beforeUpdate() {
                console.log("beforeUpdate");
                console.log(this.n);
                // debugger  这时页面n呈现的是1 但是数据是2 所以不能保持同步
            },
            /*   此时的数据是新的 页面也是新的  即页面和数据保持同步 */
            updated() {
                console.log('updated');
                console.log(this.n);  //此时 页面是n 是2  数据的n也是2
                // debugger
            },
            /* 销毁流程  可以调用但是不可以更新数据 */
         /*  此时 vm 中的所有data methods 指令等等 都处于可用状态 马上要执行销毁过程 一般在此阶段 关闭定时器 取消订阅消息  解绑自定义事件 等收尾操作  */
            beforeDestroy() {
                console.log("beforeDestroy");
                this.add()  // 只要进入销毁阶段 里面的东西可以调用 也可以访问  但是里面的数据修改不会触法更新
                
                
            },
        /* 销毁完成 */
            destroyed() {
                console.log("destroyed");
            },
        })
    </script>


组件的优点    组件的定义  ------ 实现应用中 局部功能代码和资源的集合 
1.不会出现依赖关系混乱 
2.可以复用 
3.容易调试,修改
4.层级清晰 
5.组件可以嵌套 

Vue组件编程化 
单文件组件 
     一个文件中只包含一个组件
非单文件组件 
     一个文件中包含n个组件 


为啥组件中data形式  用函数 不会用对象形式  
简单理解  :用对象的话 如果A想要修改data中的某一个属性  Bdata中的属性也会修改  因为对象保存的地址 只要一个修改了  其他都会修改
 用函数就不一样了 , 它返回的是一个对象  就切断了对象的联系   每返回一次 , 每一次的对象都是新的   A想修改 不回响应B
 且每个组件中的属性 都是不一样的 如果用对象  都把所有组件中的属性放到一个对象身上   ,  用函数式 会避免这个问题 
非单文件组件 
1.创建组件 定义组件
 //创建组件  第一步
        const school = Vue.extend({ //这里不用写el
            template: `
            <div>
                <h1>学校名称 : {{schoolName}}</h1>
                <h1>学校地址 : {{schoolAdress}}</h1>
                <button @click="tan">点击弹出牛逼</button>
            </div> 
            `  ,
            //这里必须写 函数的形式 
            data() {
                return {
                    schoolName: '清华',
                    schoolAdress: '北京'
                }
            },
            //可以绑定事件
            methods: {
                tan() {
                    alert('牛逼')
                }
            },
        })
2.注册组件 
局部定义 
    //局部注册 
        new Vue({
            el: '#root',
            // 第二步  注册组件 
            components: {
                /* 原始写法 
                   xuexiao : school ,
                   xuesheng : student  */
                //简写
                school,
                student
            }
        })
全局定义
   //  全局注册 
        const hello = Vue.extend({
            template: `
            <div>
                <h1>你好呀{{name}}</h1>
            </div>
            `
            ,
            data() {
                return {
                    name: '天才'
                }
            },
        })
        Vue.component('hello', hello) 
3.编写组件标签
 <div id="root">
        <!-- 第三步  使用组件-->
        <school> </school>
        <hr>
        <student></student>
        <hello></hello>
    </div>

Vue中使用组件的三大步骤 
        一.定义组件 (创建组件)
        二.注册组件
        三.使用组件(写组件标签)
一.如何定义一个组价? 
       使用Vue.extend(option) 创建  其中 options 和 new Vue(options) 时传入的那个options 几乎一样  但也有点区别 
       区别如下  1.el不要写  为啥? ---- 最终所有的组件都要经过一个vm的管理 由vm中的le决定服务那个容器 
                     2.data必须写成函数 为啥? --- 避免组件被复用时 数据从在引用关系 
        备注 :使用template 可以配置组件的结构
二.如何注册组件 
       1.局部注册 :靠new Vue的时候传入components选项 
        2.全局注册 :靠Vue.component('组件' ,组件)
三.编写组件标签
      <school></school> 

非单文件的注意事项
<!-- 
    总结 
     1.关于组件名:
         一个单词组成:
            第一种写法 (首字母小写) : my
            第二种写法 (首字母大写) : My
        多个单词组成
            第一种写法(kebab-case命名) :my-school 
            第二种写法(CameCase命名) MySchool (需要Vue 脚手架支持)
        
            备注 
              (1) 组件名尽可能的回避HTML中的已有的元素名称  列如h2 H2 都不行
              (2)可以使用name配置向指定组件在开发者工具中呈现的名字
    2.关于组件标签名
       第一种写法 <my></my>
       第二种写法 </my>
       备注 : 不使用脚手架的时候</my> 会导致后续的组件不会被渲染
    
    3.一个创建组件的简写方式
       const s ={} --> 

--------------------------------------------------------------------------------

关于vueComponent
 <!-- 关于Vuecomponent构造函数   
       1、school 组件本质是一个Vuecomponent构造函数  岂不是程序员定义的  是Vue.extend 生成的
       2. 我们只需要 写<school></school> 或者 </school>  Vue 解析是就会帮我们创建 一个 school 组件的实力列化对象
       即 Vue 帮我们执行的 new Vuecomponent
        
       3.特别注意 : 每次调用Vue.extend 的时候 返回的都是一个全新的VueComponent  
       4.关于this 指向 
         (1) 组件配置中 
         data 函数 methods 中的函数   watch中的函数  computed 中的函数 它们 的this 指向 均是Vuecomponent构造函数 
         (2)new Vue (options) 配置中
            data 函数  methods 中的函数  watch 中的函数   computed中的函数 它们的this 均是 Vue实列对象
    
        5.VueComponent 的实列对象 以后简称vc 也可以称为 组件的实力列化对象
        Vue 的实列对象  以后简称vm -->


原型的复习  
funcion Demo(){
   this.a = 1 
   this.b = 2 
}
cosnt d =  new Demo()
Demo.prototype   ------ 显示原型属性  
d.__prototype__   -------  隐式原型属性   

构造函数中的属性和方法我们称为成员   
1.实列成员   是指 在构造函数内部通过this添加的成员    (只能通过实例化对象来访问,不能通过构造函数访问实列成员) 
2.静态成员 在构造函数本身添加的成员  就是静态成员   (只能通过构造函数访问 , 不能通过实列化对象访问)

图解




问题  虽然好用  但是 比较占空间   每一次new 一个新的实列化对象的时候都会创建一个新的地址   (最重要的是 实列成员里面还有方法  ,方法比属性耗费空间)
优化方法    把所有的实列化对象里面的共享的方法 都放到构造函数里面的原型 上      

疑惑 为啥 实列化对象身上可以访问构造函数原型身上的属性和方法呢  ? 
因为实列化对象中有一个属性是__proto__  指向构造函数的prototype  

原型如果要配置多个方法 必须重新配置构造函数  




注意我们构造函数里面有一个prototype原型对象   且我们原型对象中也是一个对象 
  所以我们prototype 中也有一个__proto__  指向的是Object.prototype  
所以Object.prototype中也有一个__proto__ 指向的是null


Main.js中的render函数
为啥要用 render   因为我们在使用脚手架的运行的时候  引入的是一个残缺版vue  不能解析模板  
 render(createElement) {  //这里createElement  这个参数 是指 创建元素  
     return  createElement('h1' , '我是一个h1标签')    //第一个参数是指 要创建元素的标签名   第二个参数是指 标签里面的内容 
}

因为里面没有this的固定  所以可以简写  
render : h => createElement(App)    


修改默认配置 
修改main.js  
如果写了 就必须配置入口   否则报错    
删除vue.config.js  即可用默认的main.js 

关闭语法检查 


ref  的使用 
<template>
    <div>
        <h2 ref="cwj">欢迎来到{{name}}</h2>
         <School ref="shc" id="sc"/>
         <Student studentName="常文俊" :studentAge="19"/>
         <button @click="showName">点击我提示姓名</button>
    </div>
</template>
<script>
//引入组件
import School from './components/School.vue'
import Student from './components/Student.vue'
export default {
    name: 'App',
    components: {
        School,
        Student
    } ,
    data() {
        return {
            name : '常文俊'
        }
    },
    methods: {
        showName() {
            console.log(this); //这里的this指的是 vc  (App组件实列化对象) 
            console.log(this.$refs.cwj); //输出的是真实dom元素  
            console.log(this.$refs.shc);  //输出的是school 组件的对象
            console.log(document.getElementById('sc')); //输出的真实dom元素
        }
    },
}
</script>
总结 
  ref属性   
       1.被用来给元素或子组件注册引用信息(id的替者)
        2.应用在html标签上获取的是真实dom   应用在组件标签上获取的是实列化对象 (vc) 
        3.应用方式  
                 打标识 : <h1 ref="xxx">  或者  <School ref="xxx" />                  
                 获取  this.$refs.xxx  

props  其中不能传key这个关键字 
 功能  :让组件接受外部传过来的数据 
           (1)传递数据 
                     <Demo name="xxx" /> 
              (2) 接受数据 
                     第一种方式 (只接受) 
                       props :['name']  
                     第二种方式 (限制类型) 
                       props :{
                             name : String  
                     }  
                  第三种方式  (限制类型 , 限制必要性 ,指定默认值) 
                    props :{
                            name :{
type :String ,   // 类型
required :true ,  // 必要性
default : 'xxx'  //默认值 
                              }
                    }

重点备注 props 是只读的   vue底层会检测你对props的修改  如果进行修改  就会发出警告  
          若业务需求确实需要修改  那么请复制 props的内容data 中一份  然后修改data中的数据
 <div>
    <h1>学生姓名{{studentName}}</h1>
    <h1>学生年龄{{myStudentAge}}</h1>
    <button @click="add">  点击让年龄+1</button>
 </div>
</template>
<script>
export default {
    name : 'student-name' ,
    data() {
        return {
            myStudentAge : this.studentAge
          
        }
    }   ,
    methods: {
        add() {
            this.myStudentAge++
        }
    },
    //第一种方式   只是接受值
    /*  props :['studentName' , 'studentAge']  */
    //第二种方式    能接受值 还能控制 值的类型 如果值的类型不对 控制台会报错  
/*     props :{
        studentName:String ,
        studentAge:Number 
    } */
  /*   第三种方式   最完整的方式  */
  props :{
      studentName :{
          type : String ,
         required : true , //必须要填写的
      } ,
      studentAge :{
          type : Number ,
          default : 99 
      }
  }
//   props 里面的属性和方法不能修改   如果需求要改的 话 可以通过   data数据里面的赋值  但是名字不能一样 不然会有冲图
}
</script>
mixin 混入  
mixin 定义 


使用 

 
  功能 :可以把多个组件公用的配置取成一个混入对象   
   使用方式 
   第一步定义混合 。列如
                   {
                        data(){....} ,
                      methods : {....} 
                      .... 
                    }
第二步使用混入 例如 
            (1) 全局混入 :Vue.mixin(xxx)
            (2) 局部混入 :mixin:['xxx']


插件 

定义插件 


  使用插件 

     功能 :用于增强vue 
    本质 : 包含install 方法的一个对象  install的第一个参数是指 vue的构造函数    第二个参数是指  插件使用这传递的数据 
     定义插件 :对象.install = function (Vue,options){
                 1.添加全局过滤器
                 Vue.filter(....) 
                 2.添加全局指令 
                 Vue.directive(....)
                 3.配置全局混入(合) 
                Vue.mixin(....) 
                 4.添加实列方法 
                 Vue.prototype.$myMethod = function() {.....}
        }
使用插件 :Vue.use()

scoped 
 作用 : 让样式局部生效 ,防止冲突 
  写法 : <style scoped>


如何将数据保存到本地存储  仅供参考   通过监视属性  watch  来实现
如果对象里面的属性也需要改变   那么开启深度监视  




组件自定义事件  
     1.一种组件中通信的方式   , 适用于  : 子组件==>父组件
      2.使用函数  :A 父组件  B是子组件    B想给A传递数据  那么就要在A中给B绑定一个自定义事件   (事件的回调在A中 )
      3.绑定自定义事件  
                    1.第一种方式 : 在组件中 :  <Demo @cwj="txt"/> 或者<Demo v-on:cwj="txt" /> 
                     2.第二种方式 : 在组件中                    

备注第二种方法 更加灵活  
3.若想让自定义事件只能触发一次 可以使用  once修饰符 或者$once方法 
4.触发自定义事件: this.$emit('cwj' , 数据) 
5.解绑一个自定义事件 this.$off('cwj')         解绑多个 this.$off(['cwj1' , 'cwj2'])       全部解绑 this.$off()
6.组件上也可以绑定原生的dom事件 ,需要native 修饰符   图解 


7.注意 : 通过this.$ref.xxx.$on('cwj' , 回调) 绑定自定义事件  回调要莫配置  在methods中  那么用箭头函数   否则this指向会出现问题 


全局事件中线


消息订阅与发布 


注意 :回调函数里面第一个参数  是指  消息名  

$nextTick   

也可以  用定时器  stimeout(()=>{})  因为定时器可以推到队列中 同步代码先执行  然后才会执行 异步 



总结动画与过渡    
   1.作用:在插入 或更新或移除DOM元素时 在适合的时候给元素添加样式类名 
   2.写法 


      vue脚手架配置代理
      方法一  
         在vue.config.js 中添加如下配置 
             

         说明 :   
                 1.优点:配置简单 ,请求资源时候直接发送给前端 
                 2.缺点 :不能配置多个代理 ,不能灵活的控制请求 是否走代理
                 3.工作方式 :若按照上述配置代理  当请求了前端不存在的资源时  那么该请求会转发给服务器   (优先配置前端资源)  
 
     方法二 
    

    说明  :
       1. 优点  :可以配置多个代理  且可以控制请求是否走代理
       2.缺点 :配置代理繁琐  请求资源时必须加前缀   

Vue-resource的使用 
   1.安装 npm i vue-resource  
    2.引入 improt VueResource  from "vue-resource"  
   3.Vue.use(VueResource) 
   4.使用$http.get().then() 和  axios用法一样


插槽 
1.作用 : 让父组件可以向子组件指定位置插入html结构 ,也是一种组件通信的方式 适用于  父组件==》子组件
2.分类 : 默认插槽 , 具名插槽  , 作用域插槽 
3.使用方式 















Vuex的原理图  


Vuex中搭建


Vuex中的map方法 






Vuex模块化 






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


路由的query参数 
1.路由传参
   <ul>
   <li v-for="c in contList" :key="c.id">
    <!-- 跳转路由并携带query 参数  to的字符串写法 -->
   <!-- <router-link :to="`/Home/Title1/Detail?name=${c.name}&age=${c.age}`"> id是{{c.id}}</router-link > -->
 
    <!-- 跳转路由并携带query 参数  to的对象写法 -->
    <router-link :to="{
        path : '/Home/Title1/Detail',
        query :{
            id :c.id ,
            name : c.name ,
            age : c.age 
        }
    } "> id是{{c.id}}</router-link > 
   </li>
</ul>
2.接受路由 
<!-- $route.query 可以接受路由传来的参数 -->
   <ul>
  <li>{{$route.query.id}}</li>
  <li>{{$route.query.name}}</li>
  <li>{{$route.query.age}}</li>
   </ul>
注意如果是字符串  :   请使用 :to="`${}`"
命名路由
1.作用: 可以简化路由跳转 
2.如何使用 
 
 //1.命名
  {
        path : '/Home' ,
        component : Home ,
        children :[
         { 
            name : 'tou1', //给路由命名
             path : 'Title1' ,
         component : Title1 
         ,
         children :[
        
            {  
               name : 'xinxi' ,
               path : 'Detail' ,
            component : Detail   ,           
             }
            ]
         } ,
         { 
            name : 'tou2',
             path : 'Title2' ,
         component : Title2} 
        ]
     }
2.简化跳转 
  <ul>
   <li v-for="c in contList" :key="c.id">
    <!-- 跳转路由并携带query 参数  to的字符串写法 -->
   <!-- <router-link :to="`/Home/Title1/Detail?name=${c.name}&age=${c.age}`"> id是{{c.id}}</router-link > -->
 
    <!-- 跳转路由并携带query 参数  to的对象写法 -->
    <router-link :to="{
        name : 'xinxi',
      //  path : '/Home/Title1/Detail',
        query :{
            id :c.id ,
            name : c.name ,
            age : c.age 
        }
    } "> id是{{c.id}}</router-link > 
   </li>
</ul>
路由的params参数 
 1.配置路由 声明接受params参数 
  {
        path : '/Home' ,
        component : Home ,
        children :[
         { 
            name : 'tou1',
             path : 'Title1' ,
         component : Title1 
         ,
         children :[
        
            {  
               name : 'xinxi' ,
               path : 'Detail/:id/:name/:age' , //使用占位符声明接收params 参数
              component : Detail 
             }
            ]
         } ,
         { 
            name : 'tou2',
             path : 'Title2' ,
         component : Title2} 
        ]
     }
2.传递参数
<ul>
   <li v-for="c in contList" :key="c.id">
    <!-- 跳转路由并携带params 参数  to的字符串写法 -->
   <!-- <router-link :to="`/Home/Title1/Detail?${c.id}&${c.name}&${c.age}`"> id是{{c.id}}</router-link > -->
 
    <!-- 跳转路由并携带params 参数  to的对象写法 -->
    <router-link :to="{
        name : 'xinxi', // params  参数必须使用name不能使用path 
        params :{
            id :c.id ,
            name : c.name ,
            age : c.age 
        }
    } "> id是{{c.id}}</router-link > 
   </li>
</ul>

特别注意 : 路由跳转携带params参数时 若使用to对象的写法  则不能使用 path配置项  必须使用name配置  (重点)
3.接受参数
<!-- $route.params 可以接受路由传来的参数 -->
<ul>
  <li>{{$route.params.id}}</li>
  <li>{{$route.params.name}}</li>
  <li>{{$route.params.age}}</li>
</ul>
路由使用props配置 

  {  
               name : 'xinxi' ,
               path : 'Detail' ,  
               component : Detail  ,
               //第一种写法 值为对象 该对象中的所有key-value 都会以props的形式传递给Detail组件
  /*              props :{
                  a : 1 , 
                  b : 'hello'
               } */
               //第二种写法 布尔值  若值为布尔值得话  就会把该路由组件收到的所有params 参数  以props的形式传递给Detail组件
               // props : true 
               //第三种写法  值为函数  可以用于query参数 该函数返回的对象中每一组key-value都会通过props传给Deatil组件 
                props ($route) {
                  return {id : $route.query.id , name: $route.query.name , age : $route.query.age }
                }
             }

<router-link>的replace属性 
1.作用 : 控制路由跳转时候操作浏览器历史记录的模式 
2.浏览器的历史纪录有两种写法 分别时push 和 repalce ,push 是追加历史记录 replace 是替换当前记录 路由跳转时候 默认是push 
3..如何开启replace 模式  <router-link replace  ....> new </router-link>
 
编程式路由导航
作用 : 借助<router-link> 实现路由跳转 ,让路由跳转更加灵活 
具体编码 
   //router 的两个API
   this.$router.push({
        name : '路由名' ,
        params : {
            id : 'xx' ,
            title : xxx         
        }                   
   })
   
   this.$router.replace({
       name : '路由名' ,
        params : {
            id : 'xx' ,
            title : xxx         
        }         
   })
   
   this.$router.forward() //前进 
   this.$router.back() //后退
   this.$router.go() //可以前进可以后退
缓存路由 keep-alive 
作用 : 让不展示的路由 组件保持挂载 不被销毁 
具体编码 
<keep-alive include="News">
   <router-view></router-view>
</router-alive>
注意 include="写的是组件(name)值" 
//如果不写include 则全部缓存 
//缓存多个 
<keep-alive :include="['a','b' ,'c']">
两个新生命周期钩子
作用 :路由跳转所独有的两个钩子 ,用于捕获 路由组件激活状态
具体
 activated() { //activated 是指切入当前路由组件的时候 触发 (也叫激活)
     this.timer=   setInterval(()=>{
            this.opacity -= 0.1 ;
            if(this.opacity<=0) this.opacity=1
        },16)
    } ,
    deactivated () { //deactivated 是指切走当前的路由组件的时候触发 (也叫失活)
        clearInterval(this.timer)
    }
路由守卫
//全局前置路由守卫 --- 初始化的时候 被调用  每次路由切换之前被调用
//一共有三个参数  to指的是去哪里  from来自哪里   next 执行下去
//这样写有点麻烦 全局前置路由守卫
/* router.beforeEach((to, from, next) => { 
   console.log(to,from);
   // if(to.path === '/Home/Title1' || to.path==='/Home/Title2') {
   if(to.name === 'tou1' || to.name==='tou2') {
      //查看权限 本地储存里面的name===cwj 如果等于执行
      if(localStorage.getItem('name')==='cwj'){
         next()
      } 
   }else {
      next()
   }   
})
 */
//借助meta:{} meta 也叫路由元  谁想阻止给谁配
//这样写比较方便
//前置路由守卫  跳转前就出触发拦截
router.beforeEach((to,from,next)=>{
   console.log(to,from,next);
   if(to.meta.isAuth) { //判断是否建立权限
         //查看权限 本地储存里面的name===cwj 如果等于执行
         if(localStorage.getItem('name')==='cwj'){
            next()
         }  else {
            alert('没有权限')
         }
   }else {
         next()
    }  
})
//后置路由守卫  里面没有next  跳转后触发
router.afterEach((to,from)=>{
   console.log(to,from);
   document.title = to.meta.title ||'常文俊的页面'
})

独享路由守卫 
//借助meta:{} meta 也叫源码  谁想阻止给谁配
//单独路由守卫   进入之前执行这个函数  beforeEnter
router.beforeEnter((to,from,next)=>{
   if(to.meta.isAuth) { //判断是否建立权限
      //查看权限 本地储存里面的name===cwj 如果等于执行
      if(localStorage.getItem('name')==='cwj'){
         next()
      }  else {
         alert('没有权限')
      }
}else {
      next()
 }  
})
 //后置路由守卫  里面没有next  跳转后触发
router.afterEach((to,from)=>{
   console.log(to,from);
   document.title = to.meta.title ||'常文俊的页面'
})
组件内路由守卫
 //通过路由规则 进入该文件时候被调用
    beforeRouteEnter(to,from,next) {
      if(to.meta.isAuth) {
        if(localStorage.getItem('name') === 'cwj') {
          next()
        }else {
          alert('没有权限')
        }
      }else {
        next() //如果不放行就不显示内容
      }
    } ,
    //通过路由规则  离开该组件时候被调用
    beforeRouteLeave(to,from,next) {
      next() //如果不放行 就不会离开
    }
history与hash模式 
1.对于一个url来说 什么是hash值 ?  ------ 及其后面的内容就是hash值 
2.hash值不会包含在http请求中 即hash值不会带给服务器
3.hash模式 :
       1.地址中永远带#号 ,不美观
       2.若以后将地址第三方手机app分享 若app校验严格 , 则地址栏被标记为不合法 
       3.兼容性好 
4.history模式
    1.地址栏干净 ,美观 
    2.兼容性和hash模式相比略差 
    3.应用部署上线时需要后端人员支持 ,解决刷新页面服务端404的问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值