vue(四) – vue.js进阶语法

自定义指令

指令用于简化 DOM 操作,相当于对基础 DOM操作的一种封装. 当我们希望使用一些内置指令不具备的 DOM
功能时,可以进行自定义指令设置。

自定义全局指令

image.png

上图中:

Vue: 指的是创建vue实例使用的Vue函数;

focus: 指令名称(函数名称)

inserted: 当前设置了focus指令的函数被插入到dom中时要执行的一个钩子函数. 虽然被插入到dom中, 但不一定在页面中,也有可能是插入到父元素中了.

el: el是个形参,可选,指的是设置了当前指令的元素.

<body>
    <div id="app">
       <input type="text" v-focus>
    </div>

    <script src="lib/vue.js"></script>
    <script>
       Vue.directive("focus",{
           inserted(el){
               el.focus();
           }
       })

       var vm = new Vue({
           el:"#app"
       })
    </script>
</body>
复制代码

inserted 还可以通过 binding 查看当前指令设置的一些信息.

v-focus.a.b="100+1"可以设置一些值, =可以进行赋值.

  <div id="app">
    <input type="text" v-focus.a.b="100+1">
  </div>
  
 
    // 自定义全局指令
    Vue.directive('focus', {
      inserted (el, binding) {   //binding指的是当前指令设置的一些信息
        console.log(binding);
        el.focus();
      }
    });
复制代码

image.png

自定义局部指令

指的是可以在当前 Vue 实例或组件内使用的指令。

image.png

全局指令是directive, 没有s. 设置给元素的方式是一样的.

<body>
    <div id="app">
       <input type="text" v-focus>
    </div>

    <script src="lib/vue.js"></script>
    <script>
       var vm = new Vue({
           el:"#app",
           directives: {
               focus: {
                   inserted(el){
                       el.focus();
                   }
               }
           }
       })
    </script>
</body>
复制代码

过滤器

过滤器用于进行文本内容格式化处理。

过滤器可以在插值表达式v-bind中使用。

全局过滤器

image.png

过滤器可以在插值表达式v-bind中使用, 通过管道符|连接数据.

image.png

<body>
  <div id="app">
    <p v-bind:title="value | filterA">这是标签</p>
    <p>{{ value2 | filterA }}</p>
  </div>

  <div id="app2">
    <p>{{ value | filterA }}</p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 设置全局过滤器
    Vue.filter('filterA', function (value) {
      return value.split('-').join('');
    });


    new Vue({
      el: '#app',
      data: {
        value: 'a-b-c',
        value2: 'x-y-z'
      }
    });

    new Vue({
      el: '#app2',
      data: {
        value: 'q-w-e'
      }
    })
  </script>
</body>
复制代码

image.png

特殊用法

  1. 可以将一个数据传入到多个过滤器中进行处理。从左向右一次处理, filterA的返回值会传给filterB继续进行处理.

image.png

  1. 一个过滤器可以传入多个参数

image.png

这里要注意一个参数问题:

<p>{{ value | filterC(100,200) }}</p>

<script>
     Vue.filter("filterC", function(par1,par2,par3){
         console.log(par1,par2,par3);
     })

    new Vue({
      el: '#app',
      data: {
       value: "a-b-c",
      }
    });
</scrpt>
复制代码

function中的参数, 第一个指的是需要进行过滤的数据, 也就是这里的value; 后面的才是通过filterC(100,200) 传入的值.

image.png

给字符串加个前缀

<body>
  <div id="app">
    <p>{{ value | filterC("xxx-",200) }}</p>
  </div>

  <script src="lib/vue.js"></script>
  <script>
     Vue.filter("filterC", function(par1,par2,par3){
         return par2+par1.split("-").join("");
     })

    new Vue({
      el: '#app',
      data: {
       value: "a-b-c",
       value2: "x-y-z"
      }
    });
  </script>
</body>
复制代码

image.png

局部过滤器

局部过滤器只能在当前 Vue 实例中使用。

image.png

也可以 1. 将一个数据传入多个过滤器中处理; 2. 连续传入多个参数

<body>
  <div id="app">
    <p>{{ content | filterA }}</p>

    <p>{{ content2 | filterA }}</p>

    <p>{{ content | filterA | filterB }}</p>

    <p>{{ content | filterA | filterC('xxx-') }}</p>
  </div>

  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        content: 'a-b-c',
        content2: 'x-y-z'
      },
      filters: {
        filterA: function (value) {
          return value.split('-').join('');
        },
        filterB: function (value) {
          return value.split('').reverse().join('');
        },
        filterC (value, prefix) {
          return prefix + value;
        }
      }
    });
  </script>
复制代码

image.png

优先级

当局部过滤器和全局过滤器名称一致, 发生冲突时, 局部过滤器的优先级更高, 只会执行局部过滤器的操作.

计算属性

使用方法

计算属性使用时为属性形式,访问时会自动执行对应函数。

image.png

image.png

methods 与 computed 区别

• computed 具有缓存型,methods 没有。computed每次执行完后会对结果进行缓存, 比如下面的数组求和, 当数组没有发生变化时, 直接使用之前的结果而不是重新计算.

• computed 通过属性名访问,不需要加括号; methods 需要调用。

• computed 仅适用于计算操作。

<body>
  <div id="app">
    <p>{{ getSum() }}</p>
    <p>{{ getSum() }}</p>
    <p>{{ getSum() }}</p>

    <p>{{ getResult }}</p>
    <p>{{ getResult }}</p>
    <p>{{ getResult }}</p>
    <p>{{ getResult }}</p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        arr: [1, 2, 3, 4, 5]
      },
      methods: {
        getSum () {
          console.log('methods执行了函数功能');
          var arr = this.arr;
          var sum = 0;
          for (var i = 0; i < arr.length; i++) {
            sum += arr[i];
          }
          return sum;
        }
      },
      computed: {
        getResult () {
          console.log('computed执行了计算属性');
          var arr = this.arr;
          var sum = 0;
          for (var i = 0; i < arr.length; i++) {
            sum += arr[i];
          }
          return sum;
        }
      }
    })
  </script>
复制代码

可以看到methods每调用一次就执行一次, 而computed只执行了一次:

image.png

小练习

准备一个数组,根据数组数据创建列表。当数据大于10时创建 li,否则不创建。

思考以下三种实现方式:

  • v-if 与 v-for 结合

  • v-for 与 methods 结合(如果调用多次效率较低)

  • v-for 与 计算属性结合(推荐)

  1. v-if 与 v-for 结合
<body>
    <div id="app">
        <ul>
            <!-- 不推荐 v-if 与 v-for 同时应用与同一个元素, 效率较低 -->
            <li v-if="item>10" v-for="item in arr">{{item}}</li>
        </ul>
    </div>
    
    <script src="lib/vue.js"></script>
    <script>
        new Vue({
            el: "#app",
            data: {
                arr: [1, 11, 2, 22, 3, 33, 4, 44, 5, 55]
            }
        })
    </script>
</body>
复制代码
  1. v-for 与 methods 结合
<body>
    <div id="app">
        <ul>
            <li v-for="item in fn()">{{item}}</li>
        </ul>
    </div>
    
    <script src="lib/vue.js"></script>
    <script>
        new Vue({
            el: "#app",
            data: {
                arr: [1, 11, 2, 22, 3, 33, 4, 44, 5, 55]
            },
            methods: {
                fn(){
                    var newArr = [];
                    for(var i=0;i<this.arr.length;i++){
                        if(this.arr[i]>10){
                            newArr.push(this.arr[i])
                        }
                    }
                    return newArr
                }
            }
        })
    </script>
</body>
复制代码

3.v-for 与 计算属性结合

<body>
  <div id="app">
    <ul>
      <li v-for="item in result">{{ item }}</li>
    </ul>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        arr: [1, 11, 2, 22, 3, 33, 4, 44, 5, 55]
      },
      computed: {
        result () {
          console.log('执行了代码');
          return this.arr.filter(item => item > 10);
        }
      }
    });
  </script>
</body>
复制代码

计算属性的 setter

计算属性默认只有 getter,Vue.js 也允许给计算属性设置setter

image.png

<body>
  <div id="app">
    <p>{{ fullName }}</p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        firstName: '张',
        lastName: '三'
      },
      computed: {
        // 默认书写方式:
        /* fullName () {
          return this.firstName + this.lastName;
        } */

        // 分开书写 getter 与 setter
        fullName: {
          get () {
            return this.firstName + this.lastName;
          },
          set (newValue) {
            console.log(newValue)
            var nameArr = newValue.split(' ');
            this.firstName = nameArr[0];
            this.lastName = nameArr[1];
          }
        }
      }
    });
  </script>
</body>
复制代码

在控制台使用get和set得到的结果:
image.png

侦听器

侦听器用于监听数据变化并执行指定操作。

image.png

newValue: 新的值

oldValue: 旧的值

使用时通过给元素设置v-model="value"来进行双向数据绑定.

<body>
  <div id="app">
    <input type="text" v-model="value">
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        value: ''
      },
      watch: {
        value () {
          console.log('侦听器执行了');
        }
      }
    })
  </script>
</body>
复制代码

输入框中每次输入值, 都会导致侦听器的执行:
image.png

复杂数据类型的处理

对象

为了监听对象内部值的变化,需要将 watch 书写为对象,并设置选项 deep: true,这时通过 handler 设置处理函数。( deep只对对象有效)

image.png

<body>
    <div id="app">

    </div>
    <script src="lib/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                title: "title内容",
                obj: {
                    content1: "objcontent1",
                    content2: "objcontent2"
                }
            },
            watch: {
                title(val, oldVal){
                    console.log("title被修改了",val,oldVal);
                },
                obj :{
                    deep: true,
                    handler(val,oldVal){
                        console.log("obj被修改了",val,oldVal);
                    }
                }
            }
        })
    </script>
</body>
复制代码

image.png

注意

  1. 当更改(非替换)数组或对象内部的元素时,回调函数中的新值与旧值相同,因为它们的引用都指向同一个数组 、对象。也就是说是无法进行新旧值的对比处理的. 所以对象和数组的操作只要写一个返回值就可以了.

上面的例子中, 打开obj的新值和旧值, 发现是一样的:
image.png

数组中新值和旧址也是一样的:

数组

数组的侦听器是不需要设置deep: true的, deep只对对象有效.

• 注意:数组操作不要使用索引length,无法触发侦听器函数。要使用Vue.set(数组名, 索引, 要修改的值)

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                arr: [1,2,3,4,5]
            },
            watch: {
                arr(val,oldVal){
                    console.log("arr被修改了",val,oldVal);
                }
            }
        })
    </script>
复制代码

image.png

Vue.js 生命周期

指的是 Vue 实例的生命周期。

Vue 实例的生命周期,指的是实例从创建到运行,再到销毁的过程。

Vue.js 生命周期函数

通过设置生命周期函数,可以在生命周期的特定阶段执行功能。

生命周期函数也称为生命周期钩子。

创建阶段

beforeCreate:实例初始化之前调用。

created: 实例创建后调用(data,methods已经创建完毕了)。

beforeMount:实例挂载之前调用。

mounted: 实例挂载完毕。

特点:每个实例只能执行一次。

运行阶段

beforeUpdate:数据更新后,视图更新前调用。

updated: 视图更新后调用。

特点:执行次数不定, 按需调用。

销毁阶段

beforeDestroy:实例销毁之前调用。

destroyed: 实例销毁后调用。

特点:每个实例只能执行一次。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享