• Vue 全套教程(三),入门 Vue 必知必会


    Vue(三)

    链接地址:
    Vue 全套教程(一)
    Vue 全套教程(二)

    一、监视数据原理

    Vue 会监视 data 中所有层次的数据,自动的给每个元素添加 getter、setter。也就是说,自定义的 data 数据在变成 Vue 实例的 _data 时会给每个元素自动添加 getter、setter(数据劫持)

    基本原理:Vue 会汇总 data 中的所有属性形成一个数组,然后遍历数组中的所有元素,给每一个元素添加 getter 和 setter,setter 方法监视到 _data 中的数据发生变化时,会自动的重新解析模板,更新页面中的数据。

    注意:

    1. 这里所说的 getter、setter 指的并不是数据代理,而是 _data 中的每个属性也都会有 getter、setter,如下所示:

      代码演示:

      <body>
          <div id="root">
              <h2>名称:{{name}}</h2>
      	</div>
      </body>
      
      <script type="text/javascript">
          const vm = new Vue({
              el:'#root',
              data:{
                  name:'Jay'
              }
          })
      	console.log(vm)
      </script>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      控制台输出vm后的结果如下图:

      image-20220618165727805
    2. 数据代理指的是 Vue 实例的数据如何影响 _data 中的数据。而数据劫持指的是如何将 _data 中的数据改动体现到页面中。

    3. 对于上图,当执行 vm.name = '新名字' 时,首先会通过红框中的 setter 方法修改 _data 中的数据(数据代理),然后自动的通过蓝框中的 setter 修改页面上的值(数据劫持)。

    1.1 监视对象中的数据

    首先需要明确,Vue 只会对 new Vue 时就存在的 data 数据做数据劫持,后添加的数据默认不会做数据劫持(修改数据的值不会同步到页面上),如下所示:

    代码演示:

    <body>
        <div id="root">
            <h2>名称:{{student.name}}</h2>
            <!-- 引用的是初始化时不存在的属性 -->
            <h2>性别:{{student.sex}}</h2>
        </div>
    </body>
    
    <script type="text/javascript">
        const vm = new Vue({
            el:'#root',
            data:{
                student:{
                    name: 'Jay'
                }
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果:

    image-20220618174914491

    控制台输出 vm._data 后发现,新添加的 sex 属性并没有做数据劫持(没有添加 getter、setter 方法),所以 _data 数据的变化并没有通过 setter 重新解析到页面上,如下图:

    image-20220621085621590

    1.1.1 Vue.set()方法

    该方法用来给后添加的属性做响应式处理(可以理解为做数据劫持,添加 getter、setter 方法)

    使用方式1:

    Vue.set(要添加属性的对象,要添加的属性名/数组索引值,属性对应的值)

    使用方式2:

    vm.$set(要添加属性的对象,要添加的属性名/数组索引值,属性对应的值)

    对上述运行结果做代码演示:

    image-20220618174202106

    控制台输出 vm._data 后发现新增的 sex 属性被成功的添加 getter 和 setter 方法,后续通过 vm._data.student.sex = "女" 也可以修改页面的值(通过 setter 方法重新解析模板),如下图所示:

    image-20220618174619426

    注意:Vue.set() 方法不可以直接用来给 根data 或 根vm实例 添加属性,即第一个参数不能写成 vm._datavm

    1.2 监视数组中的数据

    如果 data 中的属性是一个数组,那么监视数组的变化首先需要数组本身发生变化,比如调用 sort、reverse 等方法,Vue 会对这些方法进行包装,自动的先将数组本身改变,然后重新解析模板,渲染新数组的数据。

    可以使得数组本身发生变化的方法:

    • push:在数组的最后添加一个元素
    • pop:删除数组的最后一个元素
    • shift:删除数组的第一个元素
    • unshift:在数组的最前面添加一个元素
    • splice:在数组的指定位置进行插入、删除、替换等操作
    • sort:对数组进行排序
    • reverse:反转数组

    注意:

    1. 无法使数组本身发生变化的方法,比如 filter 方法,更改的数据想要在页面中展示出来,需要使用新数组替换旧数组。
    2. Vue.set() 可以通过索引值给数组元素做响应式处理。

    1.3 总结

    代码演示:

    要求各个按钮完成按钮文字的功能:

    <body>
        <div id="root">
            <h3>个人信息</h3>
            <button @click="student.age++">年龄+1岁</button> <br/>
            <button @click="addSex">添加性别属性,默认值:男</button> <br/>
            <button @click="addFriend">在列表首位添加一个朋友</button> <br/>
            <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br/>
            <button @click="addHobby">末尾添加一个爱好:学习</button> <br/>
            <button @click="updateHobby">修改第二个爱好为:开车</button> <br/>
            <button @click="removeSmoke">过滤掉爱好中的烫头</button> <br/>
    
            <h3>姓名:{{student.name}}</h3>
            <h3>年龄:{{student.age}}</h3>
            <h3 v-if="student.sex">性别:{{student.sex}}</h3>
            <h3>爱好:</h3>
            <ul>
                <li v-for="(h,index) in student.hobby" :key="index">
                    {{h}}
                </li>
            </ul>
            <h3>朋友们:</h3>
            <ul>
                <li v-for="(f,index) in student.friends" :key="index">
                    {{f.name}}--{{f.age}}
                </li>
            </ul>
        </div>
    </body>
    
    <script type="text/javascript">
        const vm = new Vue({
            el:'#root',
            data:{
                student:{
                    name:'tom',
                    age:18,
                    hobby:['抽烟','喝酒','烫头'],
                    friends:[
                        {name:'jerry',age:35},
                        {name:'tony',age:36}
                    ]
                }
            },
            methods: {
                addSex(){
                    this.$set(this.student,'sex','男')
                },
                addFriend(){
                    this.student.friends.unshift({name:'jack',age:70})
                },
                updateFirstFriendName(){
                    // 数组的元素是对象时,会给对象中的所有属性做数据劫持
                    this.student.friends[0].name = '张三'
                },
                addHobby(){
                    this.student.hobby.push('学习')
                },
                updateHobby(){
                    // this.student.hobby.splice(0,1,'开车')
    
                    // 通过Vue.set方法也可以修改数组的值
    
                    // Vue.set(this.student.hobby,1,'开车')
                    this.$set(this.student.hobby,1,'开车')
                },
                removeSmoke(){
                    this.student.hobby = this.student.hobby.filter((h)=>{
                        return h !== '烫头'
                    })
                }
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    运行结果(未点击按钮):

    image-20220619105327425

    运行结果(点击所有按钮):

    image-20220619105436290

    运行结果(数据代理):

    image-20220619105835426

    可以发现,对于自定义的数据,Vue 实例只会对最外层的 student 添加 getter 和 setter 方法(student 任意层次数据发生改变,都会导致 _data 中的数据发生改变),而不会对所有的深层属性都添加 getter 和 setter。

    运行结果(数据劫持—hobby):

    image-20220619110234760

    hobby 是一个数组,所以没有 setter 和 getter,如果想要页面的数据发生变化,则需要修改数组本身。

    运行结果(数据劫持—friends):

    image-20220619110714004

    friends 虽然是一个数组,但是其中的值是对象,Vue 会给对象中的属性做数据劫持,所以直接通过上述的代码 this.student.friends[0].name = '张三' ,也可修改页面的数据。

    二、再谈v-model指令

    2.1 收集表单数据

    收集用户输入的数据可以通过 v-model 双向绑定,会分为以下几种情况:

    • 若为 <input type="text"/> 等文本输入框类型,由于用户的输入默认赋值的就是 value 属性,故 v-model 收集的是用户直接输入的数据。
    • 若为 <input type="radio"/> 单选框,则需要手动给该标签添加 value 属性,v-model 收集的是该标签的 value 属性值。
    • 若为 <input type="checkbox"/> 多选框:
      • 没有配置 value 属性,那么 v-model 收集的是布尔类型的 checked 属性(是否被选中)。
      • 已经配置 value 属性:
        • v-model 绑定的 data 属性的初始类型非数组,那么 v-model 收集的是布尔类型的 checked 属性(是否被选中)。
        • v-model 绑定的 data 属性的初始类型为数组,那么 v-model 收集的是所有多选框的 value 属性值所组成的数组。

    代码演示:

    <body>
        <div id="root">
            <!-- 给表单绑定一个提交事件,并且阻止默认的跳转页面行为去执行demo函数 -->
            <form @submit.prevent="demo">
                账号:<input type="text" v-model="userInfo.account"> <br/><br/>
                年龄:<input type="number" v-model="userInfo.age"> <br/><br/>
    
                性别:
                男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
                女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
    
                爱好---data初始非数组:
                <!-- data初始非数组 -->
                学习1<input type="checkbox" v-model="userInfo.hobby2" value="study">
                学习2<input type="checkbox" v-model="userInfo.hobby2" value="study">
                <br/><br/>
    
                爱好---data初始为数组:
                <!-- data初始为数组 -->
                学习<input type="checkbox" v-model="userInfo.hobby1" value="study">
                打游戏<input type="checkbox" v-model="userInfo.hobby1" value="game">
                吃饭<input type="checkbox" v-model="userInfo.hobby1" value="eat">
                <br/><br/>
    
                所属校区
                <!-- select下拉框默认v-model获取的是value属性值 -->
                <select v-model="userInfo.city">
                    <option value="">请选择校区</option>
                    <option value="beijing">北京</option>
                    <option value="shanghai">上海</option>
                    <option value="shenzhen">深圳</option>
                    <option value="wuhan">武汉</option>
                </select>
                <br/><br/>
    
                其他信息:
                <textarea v-model="userInfo.other"></textarea> <br/><br/>
    
                <!-- 不需要获取value值,只需要判断布尔值即可 -->
                <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.baidu.com">《用户协议》</a>
    
                <!-- 表单中的按钮会自动触发提交事件 -->
                <button>提交</button>
            </form>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                userInfo:{
                    account:'',
                    age:18,  //默认填入18
                    sex:'female', //默认取值为女
                    hobby1:[], //初始化为数组
                    hobby2:'',
                    city:'beijing', //默认选中北京
                    other:'',
                    agree:''
                }
            },
            methods: {
                demo(){
                    alert(JSON.stringify(this.userInfo))
                }
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    运行结果:

    image-20220619160853230

    注意:

    1. <input type="number"/> 标签, 可以控制输入框只能输入数字,并且自动添加增减数字选项,如图所示:image-20220619161334697
    2. 上图中数字的取值为字符串,并非数字格式

    2.2 三个修饰符

    • lazy:输入框失去焦点后再收集数据,并非实时收集数据
    • number:输入的字符串转为有效的数字
    • trim:输入的数据首尾空格过滤

    代码演示:

    <body>
        <div id="root">
            <form>
                账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
                年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
                其他信息:<textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
            </form>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                userInfo:{
                    account:'',
                    age:'',
                    other:''
                }
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    运行结果:

    image-20220619172542016
    1. 输入字符之前、之后的空格被自动删除,但是字符中的空格不会被删除
    2. 输入的数字转为数字格式而不是字符串
    3. 其他信息会全部输入并且失焦后才会获取到值

    三、过滤器

    定义:

    过滤器(函数)用来对数据进行处理后再显示。

    用法:

    • 注册过滤器:
      • 全局:Vue.filter(过滤器名称,过滤器处理数据的函数)
      • 局部:new Vue{filters:{过滤器1名称(参数){处理过程},过滤器2...}}
    • 使用过滤器:
      • 插值语句:{{要处理的数据 | 过滤器名称}}
      • 单向绑定:v-bind:属性 = "要处理的数据 | 过滤器名称"

    处理过程:

    1. 要处理的数据自动的作为参数传递给过滤器函数,过滤器函数的返回值替换整个插值表达式或属性值。
    2. 过滤器是不需要传递实参的,自动的将要处理的数据作为参数传递给过滤器函数。
    3. 过滤器函数也可以接收额外的参数,但是第一个形参永远是要处理的数据。

    代码演示:

    <body>
        <div id="root">
            <!-- 过滤器函数不使用参数 -->
            <h3>现在是:{{msg | Formater1}}</h3>
            <!-- 过滤器函数传参 -->
            <h3>现在是:{{msg | Formater2('一路向北')}}</h3>
        </div>
    
        <div id="root2">
            <h2>{{msg | mySlice}}</h2>
        </div>
    </body>
    
    <script type="text/javascript">
    
        //全局过滤器,多个容器都可以使用
        Vue.filter('mySlice',function(value){
            return value.slice(0,4)
        })
    
        new Vue({
            el:'#root',
            data:{
                msg:'Jay111'
            },
            //局部过滤器,仅供div标签为root的容器使用
            filters:{
                // 不传递实参默认value获取的是要处理的数据
                Formater1(value){
                    return value.slice(0,3)
                },
                // 第一个参数永远是要处理的数据,第二个参数为传递的参数
                Formater2(value, str){
                    return value + str
                }
            }
        })
    
        new Vue({
            el:'#root2',
            data:{
                msg:'1111Hello'
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    运行结果:

    image-20220620222014988

    注意:

    1. 过滤器并没有改变原本的数据,而是产生新的数据替换原位置的值。

    2. 多个过滤器可以串联使用,如下列代码所示:

      {{msg | Formater1 | mySlice}},要被修改的数据 msg 作为参数传递给 Formater1 过滤器,Formater1 过滤器的返回值作为参数传递给 mySlice 过滤器。

    四、指令

    4.1 内置指令

    4.1.1 v-text

    向其所在的标签渲染指定的文本内容。

    注意:

    1. 与插值表达式的区别:v-text 会替换标签中的所有内容,而插值表达式不会替换。
    2. 该指令仅将所有数据渲染为文本,不会解析标签。

    代码演示:

    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <div>没有被替换,{{name}}</div>
            <div v-text="name">会被覆盖掉哦</div>
            <div v-text="str"></div>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                name:'Jay',
                str:'<h3>你好啊!</h3>'
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果:

    image-20220621202721663

    4.1.2 v-html

    向其所在的标签渲染指定的文本内容,与 v-text 的不同是,会解析标签。

    代码演示:

    <body>
        <div id="root">
            <div v-html="str">被替换掉了哦</div>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                str:'<h3>你好啊!</h3>',
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行结果:

    image-20220621203110931

    注意:由于 v-html 会解析标签,所以存在一定的安全隐患,容易导致 XSS 攻击。

    4.1.3 v-cloak

    v-cloak 没有属性值,Vue 实例在创建完毕并接管容器之后,会自动的删除所有 v-cloak 属性。

    作用:

    有时 JS 文件引入慢时,会出现 JS 阻塞现象,即 Vue 实例并不会立即创建,某些情况下页面上的标签会先展示出来,导致如插值表达式没有被解析就展示在了页面上。

    使用 v-cloak 指令配合 css 样式的 display:none 属性,可以避免页面出现未经解析的模板。

    代码演示:

    思路:给包含 v-cloak 属性的所有标签使用 css 样式的 display:none 属性,Vue 实例没有被加载出来之前,样式被隐藏,不会展示在页面上。当 Vue 实例加载之后,v-cloak 属性消失,css 样式的 display:none 属性失效,成功将解析后的结果展示在页面上。

    <head>
        <meta charset="UTF-8" />
        <title>v-cloak指令</title>
        <!-- 隐藏属性的样式 -->
        <style>
            /* 中括号表示所有使用v-cloak属性的标签 */
            [v-cloak]{
                display:none;
            }
        </style>
    </head>
    <body>
        <div id="root">
            <h2 v-cloak>{{name}}</h2>
        </div>
        <!-- 先展示结果,后引入 JS 标签,假设由于网速该 JS 标签在5秒之后才会被引入,会导致页面加载未解析的插值表达式 -->
        <script type="text/javascript" src="https://xxx.vue.js"></script>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                name:'Jay'
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    运行结果:

    页面空白5秒之后,显示 Jay,不会出现未解析的模板。

    4.1.4 v-once

    v-once 没有属性值,v-once 所在的标签在初次动态渲染之后,就视为静态内容,之后的数据不会再改变。

    代码演示:

    <body>
        <div id="root">
            <h2 v-once>初始化的n值是:{{n}}</h2>
            <h2>当前的n值是:{{n}}</h2>
            <button @click="n++">点我n+1</button>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                n:1
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行结果:

    点击了5次按钮:

    image-20220621225339906

    4.1.5 v-pre

    v-pre 没有属性值,v-pre 可以让其所在的标签跳过 Vue 的解析,如果使用在没有指令语法或插值表达式的标签中,可以加快编译过程。

    代码演示:

    <body>
        <div id="root">
            <h2 v-pre>当前的n值是:{{n}}</h2>
            <h2>当前的n值是:{{n}}</h2>
            <button @click="n++">点我n+1</button>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                n:1
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行结果:

    点击了5次按钮:

    image-20220621230112833

    4.2 自定义指令

    Vue 除了内置指令之外支持使用者自定义指令,当调用自定义指令时完成某一操作,自定义指令需要使用 directives 关键字。

    4.2.1 函数式

    定义:

    函数需要定义两个参数,参数1表示使用自定义指令所在标签的所有信息,参数2表示指令与绑定数据的一些信息。

    <body>
        <div id="root">
            <h2>
                <!-- 在需要使用的位置使用 v-函数名 即可完成big函数内的功能 -->
                <span v-big="n"></span>
            </h2>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                n:1
            },
            // 自定义指令
            directives:{
                big(element,binding){
                    console.log(element,binding) 
                    element.innerText = binding.value * 10
                }
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    运行结果:

    页面会显示10,控制台输出:

    image-20220623192915839

    注意:

    1. 自定义函数被调用的时间:
      • 指令与标签第一次成功绑定时(绑定不代表会显示在页面上,绑定是内存操作)
      • 指令所在的模板(div标签中的内容)被重新解析时
    2. 指令定义时不加 v-,使用时要加 v-

    4.2.2 对象式

    函数式的缺点是无法在指定的时间进行某一操作。

    使用对象式的方式,需要在值中定义三个函数:

    • bind(element,binding){}:指令与标签成功绑定时会自动调用
    • inserted(element,binding){}:指令所在的标签被插入页面时会自动调用
    • update(element,binding){}:指令所在的模板被重新解析时会自动调用

    代码演示:

    需求:输入框在页面初始展示时自动获取焦点,点击按钮之后,输入框内的值加一并获取焦点。

    注意:不能使用函数式,因为函数式在第一次绑定成功(仅在内存中)就会调用函数获取焦点,这个时候页面上并没有输入框,所以无法获取焦点,必须要等到页面中有元素才可以获取焦点。

    <body>
        <div id="root">
            <!-- 使用自定义指令v-fbind -->
            <input type="text" v-fbind:value="n">
            <button @click="n++">点我n+1</button>
        </div>
    </body>
    
    <script type="text/javascript">
        new Vue({
            el:'#root',
            data:{
                n:1
            },
            directives:{
                fbind:{
                    //指令与标签成功绑定时会自动调用
                    bind(element,binding){
                        element.value = binding.value
                    }, 
                    //指令所在的标签被插入页面时会自动调用
                    inserted(element,binding){
                        //获取焦点
                        element.focus()
                    },
                    //指令所在的模板被重新解析时会自动调用
                    update(element,binding){
                        element.value = binding.value
                        element.focus()
                    }
                }
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    4.2.3 全局指令

    局部方式仅指定的 div 标签(容器)可以使用,全局指令可以让所有容器都可以使用。

    代码演示:

    // 对象式
    Vue.directive('fbind',{
        bind(element,binding){
            element.value = binding.value
        },
        inserted(element,binding){
            element.focus()
        },
        update(element,binding){
            element.value = binding.value
        }
    }) 
    
    //函数式
    Vue.directive('fbind',function(element,binding) {
        console.log(element,binding) 
    }) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意:

    1. 自定义指令的命名方式非驼峰式,而是不同的单词使用 ‘-’ 分隔开,比如:

      //使用指令:
      v-big-number
      
      //定义指令:
      'big-number'(element,binding){
          console.log(element, binding)
      },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      由于定义函数时,JS 简写形式无法识别 ‘-’,所以函数名必须使用加单引号的非简写形式。

    2. 不论函数式还是对象式,函数中的 this 均表示 window 非 vm(指令不需要Vue管理)

  • 相关阅读:
    死锁的成因及避免
    UDP网络通信收发包原理即代码
    一文搞懂│php 中的 DI 依赖注入
    Windows用户、组的管理
    工具篇之Axure RP 10的使用
    docker swarm 布署minio集群
    Flutter笔记:完全基于Flutter绘图技术绘制一个精美的Dash图标(上)
    你真的精通HTML吗?——那些“看不见”的HTML标签及其使用场景
    07_项目开发_用户信息列表
    前端:nodejs多版本管理工具nvm
  • 原文地址:https://blog.csdn.net/weixin_49343190/article/details/125496306