美文网首页
Vue学习笔记

Vue学习笔记

作者: 男人宫 | 来源:发表于2022-08-18 13:46 被阅读0次

    初始Vue

    • 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
    • root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
    • root容器里的代码被称为vue模板
    • Vue实例和容器是一一对应的
    • 真实开发中只有一个Vue实例,并且会配合组件一起使用
    • {{xxx}}中的xxx要写js表达式,并且xxx可以自动读取到data中的所有属性,一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新
    • js表达式和js语句的区别:表达式:一个表达式会产生一个值,并且可以放在任何一个需要值的地方,如:a,q+b,function(1),x===y?a:b;js语句:if(),for()
    <body>
      <div id="root">
        <h1>hello,{{name}}</h1>
      </div>
      <script>
        Vue.config.productionTip = false //防止vue在启动时生成生产提示
        //创建Vue实例
        const x  = new Vue({
          el:'#root',  //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
          data:{   //data中用于存储数据,数据供el所指定的容器去使用
            name:"呵呵世界"
          }
        })
      </script>
    </body>
    

    模板语法

    • 插值语法:

      功能:用于解析标签体内容

      写法:{{xxx}},xxx是js表达式,并且可以直接读取到data中的所有属性
    • 指令语法:

      功能:用于解析标签(包括:标签属性,标签体内容,绑定事件...)
      举例:v-bind:href="xxx" 或 简写成 :href="xxx",xxx同样要写成js表达式,并且可以直接读取data值的所有值

    数据绑定

    vue中有两种数据绑定的方式

    • 单向绑定(v-bind):数据只能从data流向页面
    • 双向数据流(v-model):数据不仅能从data流向页面,还能从页面流向data

    1.双向绑定一般懂用于表单类元素上(如:input,select等),2.v-model:value 可以简写成v-model,因为v-model默认的是value的值

    el与data的两种写法

    • el的两种写法:a:new Vue()的时候配置el属性,b:先创建Vue实例,随后通过vm.$mount("#root")指定el的值
    • data的两种写法:a:对象式,b:函数式.如何选择:在组件中写的时候必须用函数式,否则会报错.

    一个重要的原则:由Vue管理的函数,一定不要写成箭头函数,一旦写成箭头函数,this的指向就不再是Vue实例了

    Object.defineProperty

    <script>
       let number = 18
       let person = {
         name:'张三',
         sex:'男',
       }
       Object.defineProperties(person,'age',{
        //  value:15,
        //  enumerable:true, //控制属性是否可以枚举,默认false
        //  writeable:true, //控制属性是否可以被修改.默认fasle
        //  configurable:true,//控制属性是否可以被删除.默认false
    
         get(){ //当有人读取person的age属性值时,get函数(getter)就会被调用,且返回值就是age的值
          console.log("有人读取age属性了")
            return number
         },
         set(value){  //当有人修改age属性时,set函数(setter)就会被调用,切会收到修改的具体值
           console.log("有人修改了age的值,且值是",value)
           number = value
         }
       })
      </script>
    

    数据代理

    • 通过一个对象代理对另一个对象中属性的操作(读/写)
    let obj = {x:100}
      let obj2 = {y:200}
    
      Object.defineProperties(obj2,'x',{
        get(){
          return obj.x
        },
        set(value){
          obj.x = value
        }
      })
      console.log(obj2.x) //输出结果为100
      obj2.x = 300,
      console.log(obj.x) //输出值为300 直接打印obj也可以看出
      
      //上述代码通过数据代理,通过obj2就可以操作obj中x的值
    

    Vue中的数据代理

    • 1.Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
    • 2.Vue中数据代理的好处:更加方便的操作data中的数据
    • 3.基本原理:通过Object.defineProperties()把data中的所有属性添加到vm身上.为每一个添加vm身上的属性都指定一个对应的setter和getter.在getter和setter内部去操作(读/写)data中对应的属性

    常见指令

    • 事件处理v-on:xxx

    事件的基本使用:1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名.2.事件的回调需要配置在methods对象中,最终会在vm上.3.mehods中配置的函数,不要用箭头函数,否则this就不是vm了.4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象.5.@click="demo"和@click=demo($event)效果一样,但后者可以传参

     <!-- <button v-on:click="showinfo"></button>
    <button v-on:click="showinfo1($event,66)"></button> -->
    <button @click="showinfo"></button>  
    <button @click="showinfo1($event,66)"></button>
    <!-- v-on:click可简写成@click -->
    
    
    vue中的事件修饰符
    • prevent 阻止默认事件(常用)
    • stop 阻止冒泡事件(常用)
    • once 事件只触发一次(常用)
    • capture 使用事件的捕获模式
    • self 只有event.target是当前操作的元素时才触发事件
    • passive 事件的默认行为立即执行,无需等待事件回调执行完毕
    键盘事件
    • enter 会车键
    • delete 删除
    • esc 退出
    • tab 换行(特殊,必须配合keydown使用)

    计算属性与监视

    <body>
      <div id="root">
         <p>{{fullName}}</p>
      </div>
      <script>
       const vm = new Vue({
         dta:{
           firstName:"张",
           lastName:"三"
         },
         //计算属性
         computed:{
           //完整写法
          //  fullName:{
          //    get(){
          //      return this.firstName + '-' + this.lastName
          //    },
          //    set(value){
          //      const arr = value.split('-')
          //      this.firstName = arr[0]
          //      this.lastName = arr[1]
          //    }
          //  },
           //如果没有set至于get的话以简写
         fullName(){
          return this.firstName + '-' + this.lastName
         }
         }
       })
      </script>
    </body>
    
    深度监视
    • vue中的watch默认不监测对象内部值的改变(一层)
    • 配置deep:true可以检测对象内部的改变(多层)
    <body>
      <div id="root">
         <h2>今天天气很{{info}}</h2>
         <button @click="ishot = !ishot"></button>
      </div>
      <script>
       const vm = new Vue({
         dta:{
          ishot: false,
          numbers:{
            a:1,
            b:2
          }
         },
         //监视,不仅可以监视普通的属性,也可以监听计算属性
         watch:{
           //  ishot:{
          //   //  immediate:true, //初始化时让handler调用一次,默认为fasle
          //    handler(newVlaue,oldValue){
          //     console.log("ishot被修改了",newValue,oldValue)
          //    }
          //  },
           //监视属性简写(ishot的监听)
           ishot(newVlaue,oldValue){
            console.log("ishot被修改了",newValue,oldValue)
           },
           //监视numbers中a的变化
           'numbers.a':{
            handler(newVlaue,oldValue){
              console.log("numbers.a被修改了",newValue,oldValue)
             }
           },
           //只有有对象中有属性变化就监听(深度监听)
           numbers:{
            handler(newVlaue,oldValue){
              deep:true, //开启深度监听. 默认是false
              console.log("numbers被修改了",newValue,oldValue)
             }
           }
         }
       })
    
      //  //还可写到vm外面
      //  vm.$watch('ishot',{
      //   handler(newVlaue,oldValue){
      //         console.log("ishot被修改了",newValue,oldValue)
      //        }
      //  })
      </script>
    </body>
    

    computed和watch的区别

    1.computed能完成的功能,watch都可以完成,2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作

    两个重要小原则

    1.所被vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象

    2.所有不被vue所管理的函数(定时器的回调函数,ajax的回调函数,promise的回调函数)
    ,最好写成箭头函数,这样this的指向才是vm或组件实例对象

    绑定样式

    • class样式
      :class="xxx", xxx可以是字符串,对象,数组.字符串写法用于:类型不确定,需要动态获取.对象写法适用于:要绑定多个样式,个数不确定,名字也不确定.数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
    • style样式
      :style = "{fontSize:xxx}" 其中xxx是动态值.:style='[a,b]' 其中a,b是样式对象
    <body>
      <div id="root">
        <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定-->
         <div class="basic" :class="mood" @click="changeMood">{{name}}</div><br/><br/>
        <!-- 绑定class样式--数组写法,适用于绑定样式的个数不确定,名字也不确定 -->
         <div class="basic" :class="classArr">{{anme}}</div><br/><br/>
        <!-- 绑定class样式--对象写法,适用于绑定样式的个数确定,名字也确定,但要动态决定用不用 -->
         <div class="basic" :class="classObj">{{anme}}</div><br/><br/>
         <!-- 对象形式或者这样写 -->
         <div class="basic" :class="{'style1':false,'style2':true}">{{anme}}</div><br/><br/>
         
        <!-- 内联样式style绑定--对象写法,key中不能有-连字符,省去连字符,后面字母大写 -->
         <div class="basic" :style="{fontSize : a+'px'}">{{anme}}</div><br/><br/>
         <!-- 或者这样写 -->
         <div class="basic" :style="styleObj">{{anme}}</div><br/><br/>
         <!-- 内联样式style绑定--数组写法,数组中包括的是多个对象 -->
         <div class="basic" :style="[styleObj,styleObj2]">{{anme}}</div><br/><br/>
      </div>
      <script>
        // ps:normal,style1,style2,style3为类名,有具体的样式
       const vm = new Vue({
         dta:{
          name:"小镇做题家",
          mood:"normal",
          classArr:['style1','style2','style3'],
          classObj:{
            style1:false,
            style2:true
          },
          a:40,
          styleObj:{
            fontSize:'35px'
          },
          styleObj2:{
            backgroundColor:'red'
          }
         },
         methods: {
          changeMood(){
            this.mood = "style1"
          }
         },
        })
      </script>
    </body>
    

    条件渲染 v-show v-if

    v-show是在样式上隐藏disply:none,v-if直接不创建这个组件.在开发中如果切换频率高的显示和隐藏用v-show

    列表渲染 v-for

    可以遍历数组,字典,字符串,指定次数

    <body>
      <div id="root">
       <h2>人员列表</h2>
       <ul>
          <!----遍历数组>
         <li v-for='p in persons' :key="p.id">
         <!--可以接收两个参数,第一个参数是item,第二个参数是index-->
          <!--<li v-for='(p,index) in persons' :key="index">-->
           {{p.name}}---{{p.age}}
         </li>
       </ul>
      </div>
      <script>
       const vm = new Vue({
         dta:{
            persons:[
              {id:"001",name:"小李",age:18},
              {id:"002",name:"小红",age:19},
              {id:"003",name:"小张",age:20},
            ],
            car:{
                name:'奔驰',
                price:'30万',
                color:"红色"
                }
            }
         }
        })
      </script>
    </body>
    
    Vue中key的作用

    key是虚拟Dom对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟Dom,随后Vue进行新虚拟Dom与旧虚拟Dom的差异比较,比较规则如下:

    • 旧虚拟Dom中找到了与新虚拟Dom相同的key:1.若虚拟Dom中内容没有变化,直接使用之前的真实Dom.2.若虚拟Dom中内容变化了,则生成新的真实Dom,随后替换掉页面中之前变化的真实Dom
    • 旧虚拟Dom中未找到与新虚拟Dom相同的key:创建新的真实Dom,随后渲染到页面

    Vue监视数据的原理

    1.vue会检测data中的所有层次的数据

    2.如何检测对象中的数据

    通过setter实现监视,且要在new Vue的时就传入检测的数据

    • 对象中后裔追加的属性,Vue默认不做响应式处理
    • 如需给后添加的属性做响应式,请使用如下API:
    Vue.set(target,propertyName/index,value)或者Vue.$set(target,propertyName/index,value)
    

    3.如何检测数组中的数据?

    通过包装数组更新元素方法的实现,本质上就是做了两件事

    • 1.调用原生对应的方法对数组进行更新
    • 2.重新解析模板,进而更新页面
      4.在Vue中修改数组中的某个元素一定要用如下方法(不要用下标赋值的方法去做):

      1.使用这些API:push(),pop(),shift(),splice(),sort(),reverse()

      2.Vue.set() 或 Vue.$set()

    特别注意:Vue.set()和Vue.$set()不能给vm或者vm的根元素(data)添加属性

    input表单有关

    • 若:<input type="text"/>,则v-model收集的是vlaue值,用户输入的就是value
    • 若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值
    • 若:<input type="checkbox"/>
      1.没有配置input的value值,那么收集的就是checked(勾选 或 未勾选,是布尔值)

      2.配置input的value值:

      (1)v-model的初始值是非数组,那么收集的就是checked(勾选 或 未勾选,是布尔值)

      (2)v-model的初始值是数组,那么收集的就是value值组成的数组

    v-model的三个修饰符:lazy:失去焦点再收集数据.number:输入字符串转为有效的数组.trim:输入收尾空格过滤

    过滤器

    定义:对现实的数据进行特定格式化后再显示(适用于一些简单的逻辑处理)

    语法:

    1.注册过滤器:Vue.filter(name,callback) 或 new Vue{ filter:{} }

    2.使用过滤器:{{xxx | 过滤器名}} 或v-bind:"xxx | 过滤器名"

    备注: 1.过滤器也可以接收额外的参数,多个过滤器也可以串联.2.并没有改变原本的数据,是产生新的对应的数据.(过滤器的值是挨个传递的,第一个过滤器返回的值作为第二个返回值的参数使用值)

    <body>
      <div id="root">
       <h2>过滤器,显示格式化之后的时间</h2>
      <h3>现在的时间是:{{time}}</h3>
      <h3>现在的时间是):{{time | timeForamter}}</h3>
      <h3>现在的时间是:{{time | timeForamter('YYYY_MM_DD') | mySlice}}</h3>
      <h3 :msg="msg | amySlice"></h3>
      </div>
      <script>
       const vm = new Vue({
         dta:{
           time:16358527825,
           msg:"你好,世界啊"
         },
        //  局部过滤器
         filters:{
           timeForamter(value,str='YYYY年MM月DD日 HH:mm:ss'){
            //  time作为参数value的值
              return dayjs(value).format(str)
           },
           mySlice(){ 
              return value.slice(0,4)
           }
         }
        })
    
        //全局过滤器
        Vue.filters('amySlice',function(value){
          return value.slice(0,4)
        })
      </script>
    </body>
    

    内置指令

    • v-text:向其所在的节点中渲染文本内容,与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会
    • v-html:像指定节点渲染包含html结构的内容.ps:v-html有安全性问题,容易导致xss攻击(获取到网站上的cookie)
    • v-cloak:可以通过设置属性形式[v-cloak]的display:none在数据未加载之前隐藏节点,避免出现插值语法
    • v-once:只渲染一次
    • v-pre:预编译指令,跳过其所在的节点编译过程(不会解析节点所在的插值语法,指令语法)

    自定义指令

    <body>
      <!-- 
         需求一:定义一个v-big指令,和v-text功能类似,但回把绑定的数值放大10倍
         需求二:定义一个v-fbind指令,和v-bind功能类似,但可以让其绑定的input元素默认获取焦点
         自定义指令总结:
           一.定义语法:
           1.局部指令: new Vue({
             directives:{
               指令名:配置对象
             }
           })
           或者 new Vue({
             directives(){
    
             }
           })
           2.全局指令:
           Vue.directive(指令名,配置对象) 或者 Vue.directive(指令名,回调函数)
           二.配置中常用的三个回调:
           1.bind:指令与元素绑定时调用
           2.inserted:指令所在的元素被插入页面时
           3.update:指令所在的模板结构被重新解析时调用
           三.备注:
           1.指令定义时不用加v-,但使用时需要加v-.
           2.指令如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
       -->
      <div id="root">
      <h2>{{name}}</h2>
      <h2>当前的值是:<span v-text="n"></span></h2>
      <h2>增加10倍的值是:<span v-big="n"></span></h2>
      <button @click="n++"></button>
      <input type="text" v-fbind:value='n' />
      </div>
      <script>
       const vm = new Vue({
         dta:{
           name:"世界你好",
           n:1
         },
        // 注意:自定义指令里面的this都是window,不是vm
        directives:{
          // big函数何时会被调用?1.指令与元素成功绑定时(一上来).2.指令所在的模板被重新解析时
          big(element,binding){
            // element指令所在的真实dom,binding是个对象,其中value是绑定的值
             console.log('big')
             element.innerText = binding.value * 10
          },
          fbind:{
            // 钩子函数
            // 指令与元素绑定成功时调用
            bind(element,binding){
             element.value = binding.value
            },
            // 指令所在元素被插入页面时(获取焦点看,拿到父元素)
            inserted(element,binding){
              element.focus()
            },
            // 指令所在的模板被重新解析时
            update(element,binding){
              element.value = binding.value
              element.focus()
            }
          }
        }
        })
        // --------------------------------------------------------------------------
        // 全局的自定义指令写法
        Vue.directive("fbind",{
           // 指令与元素绑定成功时调用
           bind(element,binding){
             element.value = binding.value
            },
            // 指令所在元素被插入页面时(获取焦点看,拿到父元素)
            inserted(element,binding){
              element.focus()
            },
            // 指令所在的模板被重新解析时
            update(element,binding){
              element.value = binding.value
              element.focus()
            }
        })
        Vue.directive('big',function(element,binding){
          console.log('big')
          element.innerText = binding.value * 10
        })
      </script>
    </body>
    
    

    生命周期

    常用的生命周期钩子:

    1.mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息[等初始化操作]

    2.beforeDestroy:清除定时器,解绑自定义事件,取消订阅消息等[收尾工作]

    关于销毁Vue实例:

    1.销毁后借助Vue开发者工具看不到任何消息

    2.销毁后自定义事件会失效,但原生的Dom事件依然有效

    3.一般不会在beforeFestory操作数据,因为即便操作数据,也不会再触发更新流程

    //无法通过vm访问data中的数据,methods中的方法
         beforeCreate() {
           
         },
        //可以通过vm访问到data中的数据,methods中配置的方法
         created() {
           
         },
        // 此时1.页面呈现的是未经Vue编译的Dom结构.2.所有对Dom的操作,最终都不奏效
         beforeMount() {
           
         },
         //Vue完成模板的解析,并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted.此时1.页面中呈现的是经过Vue编译的Dom.2.对Dom的操作均有效(尽可能避免).
         //至此初始化过程结束,一般在此进行:开启定时器,发送网络请求,订阅消息,绑定自定义事件等初始化操作
        mounted() {
          
        },
        //此时:数据是新的,但页面是旧的,即:页面尚未和数据保持同步
        beforeUpdate() {
          
        },
        // 此时:数据是新的,页面也是新的.即:页面和数据保持同步
        updated() {
          
        },
        // 此时:vm中所有的:data,methods,指令等等.都处于可用状态,马上要执行销毁过程.一般在此阶段:关闭定时器,取消订阅消息,解绑自定义事案件等收尾操作
        beforeDestroy() {
          
        },
        // 销毁完毕
        destroyed() {
          
        },
    
    

    组件

    实现应用中局部功能代码和资源的集合.分为非单文件组件和单文件组件.非单文件一般是在html中包含很多组件.单文件组件一般是值一个.vue文件就是一个组件

    使用(非单文件组价)组件的步骤:

    • 1.创建组件
     //Vue.extend()可以省略
     const school =  Vue.extend({
          // 注意Vue2只允许也有个根标签
          template:`
          <div>
           <h3>{{schoolname}}</h3>
           <h3>{{schooladdress}}</h3>
          </div>
          `,
          // 组件中的data必须用函数式,不然不能保证数据修改不互相影响
          data() {
            return {
              schoolname:'上海高级中学',
              schooladdress:'青浦区十二河西路45号'
            }
          },
        })
    
    • 2.注册组件
     const vm = new Vue({
         dta:{
           name:"世界你好",
           n:1
         },
        //  此处为局部注册
         components:{
          school:school
         }
     })
     
     //全局注册
    vue.component('school',school)
        
    
    • 3.使用组件
     <div id="root">
       <school></school>
      </div>
    
    • 关于组件名的注意点:
      一个单词组成的:school,School.多个单词组成的my-school,MyScool(需要脚手架支持)
    关于VueComponent
    • 1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
    • 2.我们只需要写<school/>或<school></school>,Vue解析时会帮助我们创school的实例对象,即帮助我们执行:new VueComponent(optios)
    • 3.特别注意:每次调用Vue.extend({}),返回的都是一个全新的VueComponent
    • 4.关于this的指向
      (1).组件配置中:

      data函数.methods函数,watch中的函数,computed中的函数,他们的this均是(VueComponent实例对象)

      (2).new Vue()配置中:

      data函数.methods函数,watch中的函数,computed中的函数,他们的this均是(Vue实例对象)
    • 5.Vuecomponent的实例对象,以后简称VC(也可成为组件实例对象).vue的实例对象简称VM

    Vue中重要的内置关系

    • 1.VueComponent.prototype.proto === Vue.prototype
    • 2.为什么有这个内置关系:让组件的实例对象(vc)可以访问到Vue原型上的属性和方法
    //参考原型
    //实例的隐式原型属性永远指向自己缔造者的原型对象
     //定义一个构造函数
        function Demo(){
          this.a = 1
          this.b = 2
        }
        //创建一个demo的实例对象
        const d = new Demo()
        console.log(Demo.prototype) //显式原型属性(只有函数才有的)
        console.log(d.__proto__) //隐式原型属性(对象中有的)
    
        //指向同一个原型对象
        console.log(Demo.prototype === d.__proto__) //输出true
    
        //程序员通过显式原型属性操作原型对象,追加一个x属性,值为99
        Demo.prototype.x = 99
        
        // 下面两种写法一样
        console.log(d.__proto__.x)
        console.log(d.x)
    
    

    单文件组件(xxx.vue)

    //快捷键<v
    <template>
    <!-- 组件结构 -->
      <div class="demo">
        <h2>学校名字:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="tipClick">点我</button>
      </div>
    </template>
    
    <script>
    // 与组件交互相关的代码(数据,方法等)
    // 注意:这里采用默认暴露的方式:export default,此处也省略了Vue.extend()
    export default {
      name:'school', //组件的名字,在开发者工具中会显示这个名字
      data() {
        return {
          name:"第一初级中学",
          address:"上海市海防大学路"
        }
      },
      methods: {
        tipClick(){
          alert("哈哈哈")
        }
      },
    }
    </script>
    
    <style>
    /* 样式 */
    .demo{
      background-color: aquamarine;
    }
    </style>
    

    ref属性

    • 被用来给元素或子组件注册引用信息(通过id获取元素的替代者)
    • 应用在html标签上获取的是真实的DOM元素,应用在组件标签上是组件实例对象(vc)
    • 使用方式:

      打标识:<h1 ref="xxx">...</h1> 或者<HelloWorld ref="xxx"></HelloWorld>

      获取:this.$refs.xxx
    <template>
      <div id="app">
        <h1 ref="title">略略略</h1>
        <HelloWorld ref="hell"/>
        <button @click="btnClick">点我</button>
      </div>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld.vue'
    
    export default {
      name: 'App',
      components: {
        HelloWorld
      },
      methods:{
        btnClick(){
          console.log(this.$refs.title)   //输出真实Dom元素<h1>略略略</h1>
          console.log(this.$refs.hell)  //输出HelloWorld组件的VueComponent对象(vc)
        }
      }
    }
    </script>
    
    

    props属性

    让组件接收外部传过来的数据

    • 1.数据传递
    <Demo name="xxx" />
    
    • 2.接收数据
      第一种方式(只接受):
    props:['name']<br/>
    

    第二种方式(限制类型):

    props:{
        name:String
    }
    

    第三种方式(限制类型,限制必要性,指定默认值):

    props:{
        name:{
            type:String, //类型
            require:true, //必要性
            default:'老王' //默认值
        }
    }
    

    props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告.若业务需求确实要修改,那么请复制props的内容到data中一份,然后去修改data中的数据

    mixin 混入

    // mixin.js把公共的抽离出来
    export const hunhe = {
        data:{
            x:10,
            y:100
        },
        //methods中的方法如果和被混入对象中的方法一样时,以被混入对象的为准
        methods:{
            click(){
                console.log('点击了')
            }
        },
        //和被混入对象中的钩子函数都调用
        mounted(){
            console.log('这是钩子函数')
        }
    }
    //-------------------------
    //组件vc
    // 1.导入  2.使用
    import { hunhe } from '../mixin.js'
    {
        data:{
            name:小明
        },
        //以数组形式加入混合
        mixins:[ hunhe ]
        methods:{
            
        },
        mounted(){
            
        }
    }
    

    插件

    功能:用于增强Vue

    本质:傲寒install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据.

    定义插件:

    //plugis.js
    export default {
        inastall (Vue,options){
        //1.添加全局过滤器
        Vue.filter(...)
        //2.添加全局指令
        Vue.directive(...)
        //3.配置混入对象
        Vue.mixin(...)
        //添加实例方法
        Vue.prototype.$myMethod = function(){...}
        Vue.prototype.$myProperty = xxx
        
      }
    }
    

    使用插件:

    导入 import plugin from '../plugins.js'
    //用Vue.use(插件名)
    Vue.use(plugin)
    

    scoped样式

    作用:让样式在局部生效,防止冲突.

    写法:<style scoped>

    浏览器的本地存储(localStorage,sessionStorage)

    //存储
     localStorage.setItem(key,value) //key和value必须都是字符串
    
    //读取
    localStorage.getItem(key)
    
    //删除
    localStorage.removeItem(key)
    
    //清空
    localStorage.clear()
    
    //ps:sessionStorage和localStorage的用法一样,只不过浏览器关闭sessionStorage会被清除,而localStorage不会被清除
    

    组件的自定义事件

    • 一种组件间通信的方式,适用于:子组件 ===>父组件
    • 使用场景:A是父组件,B是子组件,B想给A传数据,那么就在A中给B绑定自定义事件(事件的回调在A中)
    //通过父组件子组件传递函数类型的props事件(函数回调传值),子给父传递数据
    <School :getSchoolName='schoolNameMthod' />
    
    //通过父组件给子组件定义一个自定义事件实现:子给父传递数据(使用V-on或者@)
    <Studen @myClcik="clickMthods" /> //子组件通过this.$emit('myClcik',"666","888"),后面参数也可以包装成一个对象
    
    //通过父组件给子组件绑定一个自定义事件:子给父传递数据(使用ref)
    <HelloWoreld ref='hell' /> // this.$refs.hell.$on('监听的事件名',function(){
        //注意:如果函数直接写在这里,以普通函数的写法去写,那这里的this是HelloWoreld的VueComponent(vc).解决办法:第一种箭头函数,第二种可以把这个函数拆分到methods中去
    })
    
    //解绑自定义事件
    this.$off('clickMthods') //解绑一个
    this.$off(['clickMthods','schoolNameMthod']) //解绑多个
    this.$off() //解绑所有的自定义事件
    

    组件绑定原生事件,如@click,系统会判定会这是一个自定义事件,想要原生事件生效,应该用native修饰.@click.native='xxx'

    全局事件总线(GlobalEventbus)

    • 1.一种组件间通信的方式,适用于任意组件间通信
    • 2.安装全局事件总线:
    new Vue({
        .....
        beforeCreate(){
            Vue.prototype.$bus = this //暗转全局事件总线,$bus就是当前应用的vm
        }
    })
    
    • 3.使用事件总线
      1.接收数据:A组件想接受数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身
     methods(){ 
         demo(prams){
         .....
     }
     ....
     mounted(){
         this.$bus.$on('xxx',this.demo)
     }
     }
    

    2.提供数据:this.bus.emit('xxx',传递的数据)

    • 4.最好在beforeDestory钩子中,用$off去解绑当前组件所用到的事件

    消息的订阅与发布

    • 1.一种组件间通信的方式,适用于任意组件

    • 2.使用步骤:
      1.安装pubsub:npm i pubsub-js

      2.引入:import pubsub from 'pubsub-js'

      3.接收数据:A组件想接受数据,则在A组件中订阅消息,订阅的回调留在A组件自身.

      methods(){
          demo(parmas){
          ....
      }
      ....
      mounted(){
          this.pid = pubsub.subscribe('xxx',this.demo)
      },
      deforeDestory(){
          Pubsub.unsubscribe(this.pid)
      }
      }
      

      4.提供数据:pubsub.publish('xxx',数据)

      5.最好在deforeDestory钩子中,用Pubsub.unsubscribe(pid)去取消订阅

      nextTick

      • 1.语法:this.$nextTick(回调函数)
      • 2.作用:在下一次DOM更新结束后执行其指定的回调
      • 3.什么时候调用:当改变数据后,要基于更新后的新DOM进行某些操作时(如输入框的失去焦点),要在nextTick所指定的回调函数中执行

      Vue封装的过渡和动画

      作用:咋插入和移除DOM元素时,在合适的时候给元素添加样式类名

      写法

      (-).准备好样式:
      元素的进入样式
      1.v-enter:进入的起点
      2.v-enter-active:进入过程中
      3.v-enter-to:进入的终点
      元素离开的样式:
      1.v-leave:离开的起点
      2.v-leave-active:离开过程中
      3.v-leave-to:离开的终点
      (二)使用<transition>包裹要过渡的元素,并配置name属性
      <transition name="hello">
        <h1 v-show='isShow'>你好啊</h1>
      

    </transition>
    (三)若有多个元素需要过渡,则需要使用:<transition-group>,且每个元素都要指定key值

    > 项目中可以用第三方动画库,如:animate.css
    
    #### 配置代理(解决跨域问题)
    什么是跨域:当一个请求url的协议,域名.端口号三者之间任意一个与当前页面url不同即为跨域
    - 方法1:在Vue.config.js中添加如下配置
    

    devServer:{
    proxy:'http://localhost:5000'
    }
    //说明:
    1.优点:配置简单,请求资源时直接发给前端(8080)即可
    2.缺点:不能配置多个代理,不能灵活的控制请求是否走代理
    3.工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器

    - 方法2:编写vue.config.js配置具体代理规则
    

    module.exports= {
    devServer:{
    proxy:{
    '/api1':{//匹配所有以'/aopi1'开头的请求
    target:"http://localhost:5000",//代理目标的基础路径(不要写后面的路径了)
    ws: true,// 是否启用websockets
    changeOrigin: true,//是否开启代理
    pathRewrite:{ 'api1':'' }//匹配以api开头的路径替换成空字符串
    }
    }
    }
    }

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

    父组件:
    <Catergory>
    <div>html结构1</div>
    </Catergory>
    子组件:
    <template>
    <div>

    <slot>默认插槽内容</slot>
    </div>
    </template>

    
    二.具名插槽
    
    

    父组件:
    <Catergory>
    <template slot="center">
    <div>html结构1</div>
    </template>
    <template slot="footer">
    <div>html结构1</div>
    </template>
    </Catergory>
    子组件:
    <template>
    <div>

    <slot name="center">默认插槽内容</slot>
    <slot name="footer">默认插槽内容</slot>
    </div>
    </template>

      
      三.作用域插槽
    

    //理解:数据在组件自身,但根据数据生成的结构需要组件的使用者来决定.
    父组件:
    <Catergory>
    <template slot-scope="data>

    <ul>
    <li v-for="g in scopeData.games" :key="g">{{ g }}</li>
    </ul>
    </template>
    <template slot="footer">

    <ul>
    <h4 v-for="g in scopeData.games" :key="g">{{ g }}</h4>
    </ul>
    </template>
    </Catergory>
    子组件:
    <template>
    <div>
    <slot :games="games"></slot>
    </div>
    </template>

    <script>
    export default {
    name:"Category",
    data(){
    return{
    games:['海贼王',"猫和老鼠","大话西游"]
    }
    }
    }
    </script>

    
    #### vuex
    专门在vue中实现集中式状态,数据管理的一个vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间的通信方式,且适用于任意组件间的通信<br/>
    1.//创建文件:src/store/index.js
    

    //引入vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用插件(需要在stroe实例创建前使用,不然会报错)
    Vue.use(Vuex)

    //准备actios对象----响应组件中用户的动作
    const actions = {}
    //准备mutatios对象---修改state中的数据
    const mutatios = {}
    //准备state对象---保存具体的数据
    const state = {}
    //准备getters---用于将state中的数据进行加工
    const getters = {}

    //并暴露store
    export default new Vuex.store({
    actions,
    mutations,
    state,
    getters
    })

    2.在main.js中创建vm时传入store配置项
    

    //引入store
    import store from './store'
    ...
    //创建vm
    new Vue({
    el:'#app'
    render:h=>h(App)
    store
    })

    
    #### 路由
    1.理解:一个路由就是一组映射关系(key-vlaue),多个路由需要路由器(router)进行管理<br/>
    2.前端路由:key是路径,vlaue是组件<br/>
    ##### 基本使用
    1.安装vue-router,命令: npm i vue-router<br/>
    2.应用插件:Vue.use(VueRouter)<br/>
    3.编写router配置项
    

    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入组件
    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

    4.实现切换(active-class可配合样式进行高亮显示等)<br/>
    

    <router-link active-class="active" to="/about"></router-link>

    5.指定展示位置
    

    <router-view></router-view>

    相关文章

      网友评论

          本文标题:Vue学习笔记

          本文链接:https://www.haomeiwen.com/subject/bbeegrtx.html