Vue中常用API的使用场景

vueAPI官方文档cn.vuejs.org/v2/api/

vue提供API非常多,但常用的也就以下四种,我们会从它们的功能描述、使用场景、使用方式几个方面简单了解其如何使用,如果有能力的同学可以去看看源码和具体实现!

set、delete

功能描述

作用:更改响应式数据的属性,并确保这个新属性同样是响应式的,并且触发视图的更新,set用于向响应式对象上添加新属性,delete用于删除对象的某个属性!

set、delete的用法基本一致,这里我们将以set为例,说一下其用法!

// 用法1
Vue.set( target, key, value )
Vue.delete( target, key )
// 用法2
vm.$set( target, key, value )
vm.$delete( target, key )

说明:

  • target:目标对象
  • key:要添加的属性名
  • value:要添加的属性值

注意 delete的key值在vue2.2以上版本中支持Array + index 即list[1]用法。

使用场景

假如我们有一个商品列表,每个列表包含了商品名称、商品价格和用户购买商品的数量,这三个字段,但是在服务器端对于商品列表而言是没有用户购买商品的数量这个概念的,所以服务器只能返回商品的名称和价格,至于数量这个字段需要你自己去添加上去。

例子:

<div id="app">
    <ul>
        <li v-for="(item, index) in goods" :key="index">
            <span>名称:{{item.name}}</span>
            <span>价格:{{item.price.toFixed(2)}}</span>
            <span>数量:{{item.num}}</span>
            <br>
            <input type="button" value="+" @click="item.num += 1">
            <input type="button" value="-" @click="item.num -= 1">
        </li>
    </ul>
</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            goods: []
        },
        created () {
            let $this = this;
            setTimeout(() => {
                $this.goods = [
                    {
                        name: 'android',
                        price: 12.99
                    },
                    {
                        name: 'IOS',
                        price: 13.99
                    },
                    {
                        name: 'javaScript',
                        price: 14.99
                    }
                ];

                $this.goods.forEach(item => {
                    // item.num = 1;
                    vm.$set(item, 'num', 1);
                    // Vue.set(item, 'num', 1);
                });
            }, 3000);
        }
    });
</script>

这里我们在created函数钩子里,也就是数据挂载阶段,我们用了一个定时器定时3秒来模拟一个真实的网络请求,利用vue.set向goods的每个对象里默认传进了一个num属性,此时这个num属性就可以实时渲染到页面,并为input按钮做了点击事件,就实现了实时更新数量的需求!

注意:vm.$set和Vue.set的最终结果都是一样的,delete的用法与set类似,大家自行看说明即可!

filter

vue的过滤器分为全局过滤器和局部过滤器!

过滤器的使用

当定义了一个 filter,可以在双花括号插值{{ message|filter }}或者 v-bind 表达式(后者从 2.1.0+ 开始支持)的尾部,通过 | “管道符号”来使用我们定义的 filter。

创建过滤器

filter 的定义有两种方式:

定义全局过滤器

  1. 在创建 Vue 实例之前进行全局定义过滤器,如下,这种方式定义出的过滤器为全局使用的。
// 创建 Vue 实例之前全局定义过滤器
Vue.filter('filterName', function (value) {
  ...
  return retValue;
});

new Vue({...})

定义局部过滤器

  1. 使用 filters 选项来定义本地的过滤器,如下,这种方式定义的过滤器为单文件组件中使用。
filters: {
  filterName: function (value) {
    ...
    return retValue;
  }
}

使用场景

filter(过滤器)可以用于文本格式化,文本格式化的意思为:把一些文本内容(可以是用户输入的内容,也可以是服务器返回内容,或者是任何你想要进行文本处理的内容),按照你想要的格式进行重新编排。

假如我们需要把用户输入的英文单词首字母转为大写,其余为小写,假如我需要全局使用就可以定义一个全局过滤器!

例子:

<div id="app">
      <p>{{ message|titleCase }}</p>
    </div>
    
    <script type="text/javascript">
      
      // 定义一个全局titleCase过滤器
      Vue.filter('titleCase', function(value){
        //把字符串所有的字母变为小写,并根据空格转换成字符数组
        var arr = value.toLowerCase().split(" ")
        
        // 遍历数组
        for(var i=0; i<arr.length; i++){
          // 把第一个字符变为大写,其余变为小写
          arr[i] = arr[i].slice(0,1).toUpperCase() + arr[i].slice(1).toLowerCase();
        }
        // 加上空格返回
        return arr.join(" ");
      })
      
      var app = new Vue({
        el:"#app",
        data:{
          message: "config is an object containing vue application global configurations. "
        }
      })
      
    </script>

 

案例二:

  • 局部过滤器使用,将用户输入的车牌号转为大写
<div id="app">
    <p>鲁A·{{plateNum | plateNumFilter}}</p>
    <br>
    <input type="text" v-model="plateNum">
</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            plateNum: ''
        },
        filters: {
            // val为绑定的文本内容,在这里为 plateNum
            plateNumFilter: function (val) {
                // return 的内容就是通过 plateNumFilter过滤器重新编排之后的内容
                return val.toUpperCase().substring(0, 5);
            }
        }
    });
</script>

同时,filter 可以接收参数(filter 总接收表达式的值作为第一个参数),并且可以进行串联(多个 filter)。我们把上面的例子做一下修改,希望 filter 更加的专注,同时字符串的截取可以进行复用。

<p>陕A·{{plateNum | toUpperCaseFilter | substringFilter(5)}}</p>

Vue.filter('toUpperCaseFilter', function (val) {
    return val.toUpperCase();
});
Vue.filter('substringFilter', function (val, endNum) {
    return val.substring(0, endNum);
});

我们创建了两个 filter,其中 toUpperCaseFilter 会把文本内容转化为大写,substringFilter 会截取固定长度的字符串,这样使的它们的功能变得更加纯粹,可以更好的进行复用,这也是我们比较推荐的一种写法,利用这两个 filter 的组合,来达到我们的目的。

注意:

当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!

directive

directive创建

与 filter 一样,directive 同样有两种定义方式:

全局自定义指令

  1. 在创建 Vue 实例之前,通过 Vue.directive 进行全局定义指令,如下,这种方式定义的指令为全局使用的。
Vue.directive('directiveName', {
    ...
})

new Vue({...})

局部自定义指令

  1. 使用 directives 选项来定义本地的指令,如下,这种方式定义的指令为单文件组件中使用的。
directives: {
  directiveName: {
      ...
  }
}

功能描述

directive 为 Vue 中的自定义指令,在前面学习过的 v-model、v-show 都属于 Vue 中提供的默认指令,当 Vue 提供的默认指令不足以满足我们的需求时,就可以通过 directive 来添加自定义指令。

使用场景

我们可以假设 Vue 中并没有提供 v-show 的指令,那么就可以使用 directive 来模拟实现一下 v-show 做的事情,可以创建一个 v-demo 指令,根据我们传入的条件来控制 DOM 的显示和隐藏,先来看一下这个需求应该怎么实现。

<div id="app">
    <span v-demo="isShow">Hello v-demo</span>
</div>

<script>
    Vue.directive('demo', {
        bind: function (el, binding, vnode, oldVnode) {
            el._originalDisplay = el.style.display;
            if (!binding.value) {
                el.style.display = 'none';
            }
        },
        update: function (el, binding, vnode, oldVnode) {
            if (!binding.value === !binding.oldValue)  return;
            binding.value ? el.style.display = el._originalDisplay : el.style.display = 'none';
        },
    })
    var vm = new Vue({
        el: '#app',
        data: {
            isShow: true
        }
    });

</script>

我们可以通过控制 isShow,来控制Hello v-demo的显示和隐藏,这个比较简单不能实时渲染。

directive 的创建略微复杂,当通过 Vue.directive 方法来创建一个 directive 时,它接收两个参数,第一个参数为指令名,添加的指令名可以通过v-指令名的形式来调用,比如Vue.directive('demo', {...}),我们通过这种方式添加了一个指令名为 demo 的 directive,然后就可以在 DOM 中通过v-demo的方式来使用。

第二个参数为一个对象,这个对象提供了几个函数钩子用于描述 directive 创建、更新、销毁的各个状态,并且提供了一些参数使我们可以在这些钩子函数里面进行操作。我们看一下它提供的钩子函数都有哪些:

  • bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有,但是可以通过比较更新前后的值来忽略不必要的模板更新(详细的钩子函数参数如下)。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

以上所有的方法都接收 4 个参数,分别如下。

  • el:指令所绑定的元素,可以用来直接操作 DOM。
  • binding:一个对象,包含以下属性:
  • name:指令名,不包括 v- 前缀。
  • value:指令的绑定值,例如,v-my-directive="1 + 1" 中,绑定值为 2。
  • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用,无论值是否改变都可用。
  • expression:字符串形式的指令表达式,例如,v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
  • arg:传给指令的参数,可选,例如,v-my-directive:foo 中,参数为 "foo"。
  • modifiers:一个包含修饰符的对象,例如,v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
  • vnode:Vue 编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

除了 el 之外,其他参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

参考:vue官网自定义指令

nextTick

功能描述

官网解释 :在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

官网的说法永远都是那么官方,我们把它用大白话解释一下:

如果有一些方法需要在 DOM 渲染完成之后执行,那么就可以监听 nextTick 来获取重新渲染之后的 DOM,专业点说就是nextTick是DOM渲染的回调方法!

使用

nextTick 的使用有两种方式:

  1. Vue.nextTick( [callback, context] )
  2. vm.$nextTick( [callback] )

这两种方式的唯一区别为:this 的指向不同,使用Vue.nextTick( [callback, context] )的时候 this 默认指向 window(我们也可以根据他的第二个参数来改变它的默认指向),使用vm.$nextTick( [callback] )的时候 this 默认指向 调用它的实例(vm)。

应用场景

现在有一个<p>标签,这个标签用来承载一段描述信息,我们需要获取到

展示了描述信息之后的高度,那么就可以通过 nextTick 来实现这个需求。

let $this = this;
setTimeout(() => {
    $this.msg = '这是我们的描述信息,它很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长';
    // 我们也可以使用Vue提供的ref来获取DOM
    var msgDom = document.getElementById('msg');

    $this.$nextTick(function() {
        console.log('msg的高度为:' + msgDom.offsetHeight);
    });
}, 1000);

我们使用 nextTick 来监听 DOM 渲染完成之后的回调方法,这个时候获取的 msgDom 就是重新渲染之后的 DOM 高度。

作为一个 Promise 使用 (2.1.0 起新增,详见接下来的提示)

Vue.nextTick()
  .then(function () {
    // DOM 更新了
  })

 

2.1.0 起新增:如果没有提供回调且在支持 Promise 的环境中,则返回一个 Promise。请注意 Vue 不自带 Promise 的 polyfill,所以如果你的目标浏览器不原生支持 Promise (IE:你们都看我干嘛),你得自己提供 polyfill。

vue中常用的就这几个API,如果有兴趣学习更多,请参考开头提供的vue官方api文档!