Vue核心语法 | 青训营笔记

41 阅读8分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

Vue核心语法

vue官网常用资源

Hello,Vue!

<div id="app">
        <h1>Hello,Vue!</h1>
    </div>
​
    <script type="text/javascript">
        const vm = new Vue({
            el: '#app',
            data: {
                message : 'Hello,Vue!'
            }
        })
    </script>
  • el: 指定了Vue实例操作的容器

  • data: 用于存储数据供指定的容器使用

    • data中的所有属性都会变成vm的属性
  • {{}}: 插值语法,可以写一个js表达式

  • 注意事项:

    • Vue实例只会根据选择器接管第一个容器
    • 一个容器只能被第一个Vue实例接管
    • 真实开发中只有一个Vue实例,会配合着组件一起使用

模板语法

  • 定义:在html中的语法

插值语法

  • 使用范围:标签体内

  • 语法:

    <div id="app">
        {{something}}
    </div>
    
  • something既可以是Vue实例中的属性,又可以是任意一个js表达式

指令语法

  • 功能:用于解析标签,包括属性、绑定事件、标签体内容

  • 基本格式:v-xxx,例如用于解析属性的v-bind (例子中url为app实例中一属性)

    <a id="app" v-bind:href="url"></a>
    <!--可以简写为以下形式-->
    <a id="app" :href="url"></a>
    
    • 注意:仅有v-bind可以简写
  • ""内也可以写入js表达式或者实例内的属性或方法

数据绑定

  • 单向绑定:数据只能从data流向页面,如v-bind

    <input type="text" v-bind:value="name">
    
    • 此时,若Vue实例中的name发生变化,输入框的value会随之变化
    • 反之不成立,即输入框value变化后,Vue实例中的name值不会变化
  • 双向绑定:数据可以在data和页面之间双向流动,如v-model

    <input type="text" v-model:value="name">
    
    • 此时,name和value始终会保持一致,一个改变会导致另一个改变
    • v-model只能绑定在输入类元素上的value上,所以也可简写为v-model:"..."

el和data的替代写法

  • el的替代写法:挂载(app为一个无el的实例)

    let app = new Vue({
        ...
    })
    app.$mount("#app")
    
  • data的替代写法:函数式,通过函数返回一个对象作为data

    new Vue({
        data: function(){
            return {
                something here
            }
        }
    })
    
    • 可以简写为data(){}
    • 组件中必需使用函数式

数据代理

  • 定义:通过一个对象对另一个对象中的属性进行操作(读写)

基本用法

  • 对一个object,想要添加一个属性,应使用defineProperty

    let person = {};
    Object.defineProperty(person,'age',{
        value: 18
    })
    
    • 这样便添加了一个age:18的键值

    • 此时他并不可被更改、删除或者删除,下面通过传入更多属性来修改该特性

      let person = {};
      Object.defineProperty(person,'age',{
          value: 18,
          enumerable: true,//控制能否被遍历,默认false
          writable; true,//控制能否被修改,默认false
          configurable:true//控制能否被删除,默认false
      })
      
  • get函数(通过getter实现)

    Object.defineProperty(person,'age',{
        get(){
            some code
            return xxx;
        }
    })
    
    • 每次读取age属性时,通过调用get函数,将返回值作为age属性值
  • set函数(通过setter实现)

    Object.defineProperty(person,'age',{
        set(value){
            some code
        }
    })
    
    • 每次age的值被修改后set函数被调用
    • value为age修改后的值

Vue中的数据代理

  • 目的:更方便的操作data中的数据

  • 基本原理:

    • 通过Object.defineProperty()将data对象中所有属性添加到vm的_data上
    • 为每一个被添加的属性设置getter和setter
    • 在getter和setter内部去读写data

事件处理

绑定事件

  • 实例中在methods中添加回调函数f

  • 使用v-on:xxx="f"绑定f函数

    <button id="app"  v-on:click="hhh"></button>
    <script>
        new Vue({
            el: "#app",
            data:{},
            methods:{
                hhh(){
                    
                }
            }
        })
    </script>
    
    • 可以传一个参数作为事件对象event
    • v-on:可以简写为@click
  • 注意:methods里面的函数使用this会指向vm

  • 传入参数:

    <button id="app"  v-on:click="hhh(23)"></button>
    <script>
        new Vue({
            el: "#app",
            data:{},
            methods:{
                hhh(number){
                    
                }
            }
        })
    </script>
    
    • 在绑定事件时之间写小括号传入参数

    • 在methods内使用对应的变量接受参数

    • 如果此时需要事件对象event,则用以下写法($event表示事件对象)

      <button id="app"  v-on:click="hhh(23,$event)"></button>
      <script>
          new Vue({
              ...
              methods:{
                  hhh(number,event){
                      ...
                  }
              }
          })
      </script>
      
  • 在处理函数较简单时可以直接放入标签属性

    <button @click="count++"></button>
    
    • 此时这个count为vm实例中的属性,与methods中函数不同,此处不需要加this.

事件修饰符

  • 基本语法:

    @xxx.xxx=""
    

    例如,阻止默认行为

    <button @click.prevent="hhh"></button>
    
  • 事件修饰符及其作用

    修饰符作用
    prevent阻止默认行为
    stop阻止冒泡
    once事件仅触发一次
    capture使用捕获模式
    self只有event.target是当前操作元素才触发事件
    passive事件默认行为为立即执行,无需等待事件回调执行完毕
  • 使用多个修饰符:直接写多个.xxx

    <a href="xxx" @click.prevent.stop="xxx"
    

键盘事件

  • 在按下特定按键时触发事件,直接使用@keyup.xxx=""(xxx为按键别名)

  • 按键别名

    • Vue内置

      原始按键别名
      回车enter
      删除(捕获退格和删除)delete
      退出esc
      空格space
      换行tab
      上/下/左/右up/down/left/right
    • 对未内置的

      • 先通过event.key先查询按键名

        • 对单个单词组成的按键名(如AltControl)直接使用@keyup.小写按键名实现
        • 对于多个单词组成的按键名(如CapsLock),先将全部字母改为小写,然后不同单词间使用-连接,如@keyup.caps-lock
      • 自定义按键名

        • 先调用Vue.config.keyCodes.自定义名称=键码
        • 然后就可以用之前的方法使用自定义名称
  • 注意

    • 对于响应按键一般采用keyup

    • 但对于tab键,由于其具有切换焦点的功能,使用keyup会导致事件无法触发,所以采用keydown

    • 对系统修饰键(ctrl、alt、shift、meta(win))

      • 配合keyup使用:按下修饰键时,同时按下其它键并释放该其它键,事件触发

        • 若要在特定的按键组合下触发,如ctrl+y,则写作@keyup.ctrl.y="xxx"
      • 配合keydown使用:正常触发事件

计算属性

  • 计算属性:使用的属性不存在,而是通过已有属性进行计算得到

  • 优势:

    • 比起methods实现,通过缓存提升了效率
  • 语法:写在computed内,一定需要一个get()

    new Vue({
        xxx
        computed:{
        	key:{
        		get(){
        			some code
                    return xxx;
    			}
    		}
    	}
    })
    
  • 注意:

    • computed里面的get不能直接读取data内的属性,需要用this.xxx读取

    • get的调用时机

      • 初次读取计算属性时
      • 所依赖的数据发生变化后读取计算属性时
  • 如果需要修改计算属性,需要先定义该属性的set(value)响应修改

  • 计算属性简写:只读取不修改时可以简写为

    key(){
        getter code here
    }
    

监视属性

  • 当被监视属性变化时,调用回调函数

  • 语法1:在watch中实现

    new Vue({
    	        xxx
    	        watch:{
                    watched:{
    					handler(newVal,OldVal){
                            some code here
                        }
                    }
    				immediate: true;//默认为false,为true时初始化时handler会先被调用一次
    	        }
            })
    
    • 该语法不需要配置其它属性,只需要handler时,可简写为

      watched(newVal,oldVal){
          handler code here
      }
      
  • handler在watched变量被修改时被调用

  • watched为被监测变量,这个语句并不会声明它,它应在其它地方(一般是data)中声明

  • 语法2:通过$watch实现

    vm.$watch('被监视对象',{
        配置项,同上
    })
    

深度监视

  • 监视多级结构中某个属性的变化,需用''引用,如监测data中的number.a

    watch:{
    	'number.a' : {
    		handler(){...}
    	}
    }
    
  • 深度监视:监视多级结构中所有属性的变化

    data: {
    				number:{
    					a:1,
                        b:2
                    }
                },
    			watch: {
    				number:{
    					handler(){},
                        deep: true;//默认false,开启深度监视
                    }
                } 
    
    • 此时,number内任一属性变化都会引起handler的调用

监视原理

  • vue会监视data下所有层次的数据(包括数组内每个元素、对象内每组键值)

  • 监视原理:通过getter和setter实现

    • 对象中后追加的属性,Vue默认不做响应式处理

    • 如果想要给后追加的属性响应式处理,需要使用set,有以下两种写法

      Vue.set(vm.xxx.obj,'key','value')
      vm.$set(vm.xxx.obj,'key','value')
      
      • 注意:该方法只能给data内的对象追加属性,不可给data或vm直接追加属性
  • 监视原理(数组):给数组的修改方法进行包裹

    • 包裹后的方法具有双重功能

      • 使用原生的修改方法对数组进行修改
      • 重新解析模板、更新页面,进而实现响应式
    • 在vm中修改数组中一定要使用以下方法之一,否则Vue无法检测数组改变,进而没有响应式

      • push()
      • pop()
      • shift()
      • unshift()
      • splice()
      • sort()
      • reverse()
      • 整体替换
      • 通过Vue.set()或vm.$set修改

计算属性与监视属性

  • 关系:计算属性能完成的监视属性一定能完成,反之不成立

  • 选择:

    • 都能使用计算属性
    • 使用监视属性实现监视才能实现的功能,如异步操作

绑定样式

绑定class

  • 调整单个类名:将不变的样式写在class内,将变化的样式写在:class内动态调整

    <p class="some fixed class" :class="dynamic class"></p>
    
  • 在类的名字、个数均不确定时动态调整多个类名::class内绑定数组(数组内每个元素为一个类名)

    <p :class="cssarr"></p>
    
    • 通过操作vue内的cssarr数组即可动态调整样式

      cssarr.shift()//删除第一个类名
      cssarr.push(xxx)//添加xxx类名
      
  • 在类的名字、个数均确定时::class绑定对象

    <p :class='classarr'></p>
    
    data:{
    	classarr:{
            name1: false,
            name2: true,
        }
    }
    
    • 对象内对每个类名设置一个bool值表示是否使用

绑定style

  • 通过:style绑定对象,对象格式如例

    styleObj = {
        color: xxx,
        fontSize: xx + 'px',
    }
    
    • 注意添加单位
    • css中多个单词构成的词(如font-size)需要更改格式(如fontSize)
  • 也可以绑定样式对象数组,同时绑定多个style对象

条件渲染

  • 通过v-show条件渲染

    • 语法:
      <a v-show="exp"></a>
    
    • exp为一个值为bool类型的表达式
    • 原理:exp为false时添加display:none的样式
  • 通过v-if条件渲染

    • 语法:

      <a v-if="exp"></a>
      
    • 原理:exp为false是从DOM中删除该节点

    • 可以搭配v-else-ifv-else(不带条件)使用,但注意不能被打断

  • 批量条件渲染:通过template包裹

    • 语法

      <template v-if="exp">
          something
      </template>
      
    • template在渲染时会被去掉

    • template只能配合v-if,不能配合v-show

列表

列表渲染

  • 从数组内动态获得列表内的li

  • 语法:使用v-for循环

    <ul>
        <li v-for="p in liarr">{{p}}</li>
    </ul>
    
    • liarr为存储了li的数组
  • 一个更好的写法是为每一个li赋值一个key,例如

    <ul>
        <li v-for="p in student" :key="p.id">p.name</li>
    </ul>
    
    • key需要保证互不相同
  • 循环遍历数组过程中可以获取两个参数,第一个为传入的数组对象,第二个为index索引值,可直接使用index为key赋值(在不写key时默认给key赋值index)

    <ul>
        <li v-for="(p,index) in student" :key="index">p.name</li>
    </ul>
    
  • v-for其它用法

    • 遍历对象

      <ul>
          <li v-for="(value,key) in objname" :key="key">key:value</li>
      </ul>
      
      • 可以获取两个数据,注意顺序是value key
    • 遍历字符串

      <ul>
          <li v-for="(char,index) in objname" :key="index">char</li>
      </ul>
      
    • 遍历自然数(从1开始)

      <ul>
          <li v-for="(num,index) in 5" :key="index">num</li>
      </ul>
      
      • 上例中num遍历结果是1,2,3,4,5

key的原理

  • key的作用:key是虚拟DOM的标识,当数据发生变化时,Vue会根据key对新虚拟DOM和旧虚拟DOM进行比较(Diff算法)

  • key为Vue内部使用,只存在于虚拟DOM,不会进入真实DOM

  • Diff算法比较原则

    • 对相同key的新旧虚拟DOM

      • 若内容没变,则直接使用旧的真实DOM
      • 若内容变化,则使用新虚拟DOM生成新真实DOM
    • 对旧DOM不存在的key

      • 创建新的真实DOM
  • index作为key的问题:

    • 对数据进行逆序添加、逆序删除 等操作时导致效率低下
    • 对数据进行逆序添加、逆序删除时,若存在如输入框这类的元素可能导致界面出现错误
  • 开发中key的选择key的原则:

    • 最好使用每个数据的唯一标识作为key,如id、手机号、身份证号、学号等唯一值
    • 如果所有操作均不破坏数据原有顺序,也可以使用index

列表过滤(模糊搜索)

  • 通过计算属性配合array.filter等函数过滤,例如根据data中的keyWord模糊搜索p.name里含keyWord的项

    comuted:{
        keyWord(){
            return originarr.filter((p)=>{
                return p.name.indexOf(keyWord) !== -1
            })
        }
    }
    
    • tip: 空串是任何字符串的子集

表单数据收集

不同类型的数据收集技巧

input元素

  • text类型:直接进行数据绑定即可得到用户输入

  • radio类型:需要手动配置value的值,选择时会手机配置的value值

  • checkbox类型:

    • 用于多选:需要先手动配置value的值,并且将与之绑定的元素初始值设为[] ,收集到的元素以数组的形式存储
    • 用于单个选项:将与之绑定的元素初始值设为非数组,会收集到一个bool值表示是否选中

select元素:配置每一项的value,元素与select绑定可手机被选择项的value

textarea元素:直接绑定收集用户输入

v-model的修饰符

  • 语法:v-model.xxx=""(xxx为修饰符)

  • 修饰符列表

    修饰符作用
    lazy等待失去焦点再收集数据
    number将输入字符串转换为数字
    trim过滤首位空格

过滤器

  • 作用:对要显示的数据进行一定的格式化

  • 语法:

    • 注册过滤器:在filter内注册

      new Vue({
          filter:{
              fname(value){
                  xxx
                  return yyy;
              }
          }
      })
      
    • 使用过滤器:可以在插值语法或指令语法中使用

      {{exp | filtername}}
      
      • 使用后这段表达式将被解析为过滤器的返回值

      • exp的值将会作为过滤器的第一个参数

      • 过滤器在使用时后面加小括号可以传递更多的参数,但exp的值始终作为第一个参数,其余参数在exp后面追加

      • 可以连续调用多个过滤器处理,语法为

        {{exp | filtername1 | filtername2| filtername3}}
        

其它内置指令

  • v-text与v-html

    • 共同点:将变量绑定到显示的内容上(此时会忽略html里标签内原有的文本)

    • 不同点:v-text不解析标签,v-html会解析标签

    • 注意:v-html存在安全性问题

      • 在网站上动态渲染html是危险的,容易导致xss攻击
      • 要在可信的网页上使用v-html
      • 不能在用户输入上使用html
  • v-cloak

    • 功能:一个不需要值的特殊属性,所有的v-cloak属性在Vue接管后会消失
    • 作用:配合css可以解决网速过慢导致Vue未解析的内容直接显示的问题
  • v-once

    • 功能:一个不需要值的特殊属性,添加后在初次动态渲染后将该属性所在标签改为静态内容
  • v-pre

    • 功能:一个不需要值的特殊属性,添加后Vue不会解析该标签的内容

自定义指令

函数式

  • 调用: v-xxx=""

  • 声明:

    new Vue{
        directives:{
            xxx(element,binding){
                some code
            }
        }
    }
    
    • element是调用元素的真实DOM节点
    • binding是绑定内容的对象,包含很多关于绑定内容的信息
  • directives内的函数调用时机:

    • 指令与元素成功绑定时
    • 指令所在的模板重新解析时

对象式

  • 调用:v-xxx=""

  • 声明:

    new Vue{
        directories:{
            xxx: {
                bind(){},
                inserted(){},
                update(){}
            }
        }
    }
    
    • bind函数将会在绑定成功时调用
    • inserted函数将会指令所在元素插入页面时调用
    • update函数将会在所在模板被重新解析时被调用
    • 上面三个函数均可接受(element,binding)两个参数
  • 函数式声明可以看作把bind和update合并声明

注意事项

  • 指令名:若有多个单词,则在调用时使用v-xxx-xx-x的形式,声明时书写如下完整版本(不可简写)

    'xxx-xx-x': function(){}
    
  • this指向:directives里调用this指向均为window

  • 默认directives内的指令为局部指令,若要声明全局指令,则用

    Vue.directive('name',{
        function content
    })
    
    • 注意:vm内为directives,Vue内directive

生命周期函数

  • 别名:生命周期、生命周期回调函数、生命周期钩子

  • 定义:Vue在一定事件会调用的一些特殊名称(名称不可更改)的函数

  • this指向:生命周期函数内this指向vm或对应组件实例对象

  • 常用周期函数:

    • mounted():在页面挂载完毕时调用

      • 一般用于初始化操作,如发送Ajax请求、启动定时器、绑定自定义事件、订阅消息等
    • beforeDestroy:在实例即将被销毁时调用

      • 一般用于收尾工作,如清楚定时器、解绑自定义事件、取消订阅等