全局 API

Vue.directive

Vue 中有很多内置指令,除了内置指令外还可以根据需求使用 Vue.directive 注册自定义指令。

Vue.directive 的基本用法:

<div id="app">
    <input type="text" v-指令名称="指令的值">
</div>

<script>
    // Vue.directive():自定义指令
    // 参数1:自定义指令名称
    // 参数2:指令的配置对象
    Vue.directive('name', {
        // inserted:指令生命周期钩子函数,元素第一次插入页面中时触发
        // el:使用指令的元素本身
        // binding:指令的配置信息
        // binding.value:指令的值
        inserted (el, binding) {
            // 指令操作
        }
    })
</script>

示例:Vue.directive

入口页面(index.html):

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

<script>
    Vue.directive('focus', {
        inserted (el, binding) {
            if(binding.value) {
                // 获取焦点
                el.focus();
            }
        }
    })

    let vm = new Vue({
        el: '#app'
    })
</script>

示例效果:


Vue.use

Vue.use 主要用于在 Vue 中安装插件,通过插件可以为 Vue 添加全局功能。

Vue.use 会自动阻止多次安装同一个插件,因此,当在同一个插件上多次调用 Vue.use 时实际只会被安装一次。

Vue.js 官方提供的一些插件(如 vue-router)在检测到 Vue 是可访问的全局变量时,会自动调用 Vue.use,但在 CommonJS 等模块环境中(如 Node.js 等),始终需要 Vue.use 显式调用。

Vue.use 的基本用法:

// 定义插件对象
let pluginObj = {}

// 为插件提供install方法
// Vue:Vue实例对象
// option:插件参数
pluginObj.install = function(Vue, option) {
    // ...
}

// Vue.use():安装插件
// 参数1:插件对象
// 参数2:插件配置参数
Vue.use(pluginObj, {
    // ...
})

示例:Vue.use

入口页面(index.html):

<div id="app">
    <demo-component></demo-component>
</div>
<script>
    let MyPlugin = {}
    MyPlugin.install = function(Vue, option) {
        Vue.component('demo-component', {
        data() {
                return {
                    message: option.message
                }
            },
            template: '<h1>这是插件内定义的组件,参数为:{{option.message}}</h1>'
        })
    }

    Vue.use(MyPlugin, {
        message: 'hello, plugin'
    })

    let vm = new Vue({
        el: '#app'
    })
</script>

示例效果:


Vue.extend

Vue.extend 用于基于 Vue 构造器创建一个 Vue 子类,可以对 Vue 构造器进行扩展。

Vue.extend 的基本用法:

// Vue2继承Vue,并实现某些特性
let Vue2 = Vue.extend({
    // data:在Vue.extend()中使用时只能是一个函数
    data() {
        return {
            // ...
        }
    },
    methods: {
        // ...
    }
})

示例:Vue.extend

入口页面(index.html):

<div id="app1">
    title:{{title}}
</div>

<div id="app2">
    title:{{title}}
</div>

<script>
    // Vue2继承Vue,并实现某些特性
    let Vue2 = Vue.extend({
        // data:在Vue.extend()中使用时只能是一个函数
        data() {
            return {
                title: 'Vue2的标题'
            }
        },
        methods: {

        }
    })

    let vm1 = new Vue({
        el: '#app1',
    })

    let vm2 = new Vue2({
        el: '#app2',
    })
</script>

示例效果:


Vue.set

Vue.set 用于向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新,主要用于解决在 Vue 实例创建后,向现有对象添加新属性或修改现有属性的值的情况。

Vue.set 的基本用法:

// target:要添加或修改属性的目标对象
// key:要添加或修改的属性键
// value:要设置的属性值
Vue.set(target, key, value);

示例:Vue.set

入口页面(index.html):

<div id="app">
    name: {{user.name}}<br>
    age: {{user.age}}
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            user: {
                name: '张三'
            }
        }
    })

    Vue.set(vm.user, 'age', '18')

    setTimeout(function () {
        Vue.set(vm.user, 'age', '28')
    }, 3000)
</script>

示例效果:


Vue.mixin

Vue.mixin 用于全局注册一个混入(Mixins),它将影响之后创建的每个 Vue 实例。

Vue.mixin 的基本用法:

// 参数1:混入的对象,包含要在组件中共享的属性、方法或生命周期钩子
Vue.mixin({
    data() {
        return {
            // ...
        }
    }
})

示例:Vue.mixin

入口页面(index.html):

<div id="app">
    msg:{{msg}}
</div>

<script>
    Vue.mixin({
        data() {
            return {
                msg: '混入的数据'
            }
        },
        created() {
            console.log('混入的created')
        }
    })

    let vm = new Vue({
        el: '#app',
        created() {
            console.log('Vue实例自身的created')
        }
    })
</script>

示例效果:


实例属性

vm.$props

vm.$props 属性用于接收上级组件向下传递的数据。


示例:vm.$props

入口页面(index.html):

<div id="app">
    <h3>父组件</h3>
    请输入要传递给子组件的内容:<input v-model="msg">
    <my-component :msg="msg"></my-component>
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            msg: ""
        },
        components: {
            myComponent: {
                props: ['msg'],
                template: '<div>父组件传递给子组件的内容:{{msg}}</div>',
                watch: {
                    msg() {
                        // this.$props.msg:获取父组件传递给子组件的参数msg
                        // 也可以使用this.msg获取
                        console.log("监听到父组件传递给子组件的内容是:" + this.msg)
                    }
                }
            }
        }
    })
</script>

示例效果:


vm.$options

Vue 实例初始化时,除了传入指定的选项外,还可以传入自定义选项,自定义选项的值可以是数组、对象、函数等。

vm.$options 属性用于获取 Vue 实例中的自定义选项,自定义选项不具有响应特性。


示例:vm.$options

入口页面(index.html):

<div id="app">
    <button @click="getOption">获取自定义选项</button>
</div>

<script>
    let vm = new Vue({
        el: '#app',
        customOption: '我是自定义数据',
        methods: {
            getOption() {
                console.log(this.$options.customOption)
            }
        }
    })
</script>

示例效果:


vm.$el

vm.$el 用于访问 Vue 实例使用的根 DOM 元素。


应用示例:vm.$el

入口页面(index.html):

<div id="app">
    <p>原来的HTML</p>
</div>

<script>
    let vm = new Vue({
        el: '#app'
    })

    vm.$el.innerHTML = "<h3>new html</h3>"
</script>

示例效果:


vm.$children

vm.$children 属性用于获取当前实例的直接子组件,其获取的直接子元素并不保证按顺序,也不是响应式的。


示例:vm.$children

入口页面(index.html):

<div id="app">
    <button @click="click">获取子组件</button>
    <my-child>1</my-child>
    <my-child>2</my-child>
</div>

<script>
    Vue.component('my-child', {
        template: '<h3>子组件<slot></slot></h3>'
    })

    let vm = new Vue({
        el: '#app',
        methods : {
            click() {
                console.log(this.$children)
            }
        }
    })
</script>

示例效果:


vm.$root

vm.$root 属性用于获取当前组件树的根 Vue 实例,如果当前实例没有父实例,则获取到的是该实例本身。


示例:vm.$root

入口页面(index.html):

<div id="app">
    <my-component></my-component>
</div>

<script>
    Vue.component('my-component', {
        template: '<button @click="click">查看根实例</button>',
        methods: {
            click() {
                // 判断当前组件的根实例和vm实例是否一致
                console.log(this.$root == vm.$root)
            }
        }
    })

    let vm = new Vue({
        el: '#app'
    })
</script>

示例效果:


vm.$slots

vm.$slots 属性用于获取组件的插槽。


示例:vm.$slots

入口页面(index.html):

<div id="app">
    <my-component>
        <template v-slot:slot01>
            <div>Hello,Vue</div>
        </template>
        <template v-slot:slot02>
            <div>Hello,Component</div>
        </template>
        <template v-slot:slot03>
            <div>Hello,Slots</div>
        </template>
    </my-component>
</div>

<template id="myTemplate">
    <div>
        <slot name="slot01"></slot>
        <slot name="slot02"></slot>
        <slot name="slot03"></slot>
    </div>
</template>

<script>
    Vue.component('my-component', {
        template: '#myTemplate',
        created() {
            console.log(this.$slots)
        }
    })

    let vm = new Vue({
        el: '#app'
    })
</script>

示例效果:


vm.$attrs

vm.$attrs 属性用于获取组件的属性,获取的属性不包括 class、style、被声明为 props 的属性。


应用示例:vm.$attrs

入口页面(index.html):

<div id="app">
    <my-component id="test" class="test" name="hello"></my-component>
</div>

<script>
    Vue.component('my-component', {
        template: '<button @click="showAttrs">查看组件属性</button>',
        methods: {
            showAttrs() {
                console.log(this.$attrs)
            }
        }
    })

    let vm = new Vue({
        el: '#app'
    })
</script>

示例效果:


vm.$refs

vm.$refs 属性用于获取和修改页面内容,但一般情况下 Vue 不推荐直接使用 $refs 修改页面的内容。


应用示例:vm.$refs

入口页面(index.html):

<div id="app">
    <div id="box" ref="box">hello vue</div>
</div>
<script>
    let vm = new Vue({
        el: '#app',
        mounted() {
            console.log(document.getElementById('box').innerHTML)
            console.log(this.$refs.box.innerHTML)
        }
    })
</script>

示例效果:


全局配置

productTip

productionTip 属性用于设置在开发环境下(vue.js)是否开启提示信息。

productionTip 的基本用法:

Vue.config.productionTip = false|true;

在某些 Vue.js 版本中,通过 productionTip 属性无法关闭提示信息,其原因在于 vue.js 文件本身也有一个 productionTip 属性,在加载时,优先生效。

因此在开发环境中如果要关闭提示信息,还需要注意 vue.js 文件中的配置。

silent

silent 属性用于设置是否取消 Vue 日志和警告。

silent 的基本用法:

Vue.config.silent = true | false;

devtools

devtools 属性用于设置是否允许使用 vue-devtools 进行调试。

devtools 的基本用法:

Vue.config.devtools = true | false;

组件进阶

mixins

mixins 是一种分发 Vue 组件中可复用功能的方式。

mixins 的基本用法:

let vm = new Vue({
    el: '#app',
    // mixins:混入对象
    mixins: {
        data() {
            return {
                // ...
            }
        }
    },
    // 组件data优先级 > 混入data优先级
    data: {
        // ...
    },
    // 组件钩子函数优先级 < 混入钩子函数优先级
    created() {
        // ...
    }
})

Vue.component('my-component', {
    template: '',
    mixins: {
        // ...
    }
})

虚拟 DOM

在 Vue 2 中,引入了虚拟 DOM(Virtual DOM),虚拟 DOM 是使用 JavaScript 对象来对真实 DOM 进行描述的一种技术。

虚拟 DOM 的主要作用:

  • 提高 DOM 操作的性能:大部分情况下,使用 JavaScript 去操作跨线程的庞大 DOM 需要较高的性能,而虚拟 DOM 可以降低这一成本。
  • 实现服务器端渲染(SSR)和跨端使用:虚拟 DOM 可以用于 SSR 以及跨端使用。

虚拟 DOM 的表达方式就是把每一个标签都转为一个对象,其基本形式为:

{
    '标签',
    props: {
        // 标签上的属性和方法
    },
    children: [
    // 标签的内容或者子节点
    ]
}

应用示例:虚拟 DOM

在 Vue 中,有一个 template 模板:

<template>
    <div id="box" class="container">
        <h1>Hello,Vue</h1>
    </div>
</template>

该模板用虚拟 DOM 表示为:

{
    'div',
    props: { id:'box', class:'container' },
    children: [
        { tag: 'h1', children:'Hello,Vue' }
    ]
}

render + createElement

在 Vue 中可以使用 render 函数实现对虚拟 DOM 的操作,在 render 函数的返回值中,需要调用 createElement 函数来创建元素。

createElement 函数返回的并不是一个实际的 DOM 元素,它返回的其实是一个描述节点,用来告诉 Vue 在页面上需要渲染什么样的节点,描述节点称为虚拟节点(Virtual Node,VNode)。


应用示例:render + createElement

入口页面(index.html):

<div id="app">
    <my-component></my-component>
</div>

<script>
    Vue.component('my-component', {
        render(createElement) {
            return createElement('p', {
                style: {
                    color: 'aqua'
                }
            }, '成功渲染')
        }
    })

    let vm = new Vue({
        el: '#app',
    })
</script>

示例效果:


diff 算法

diff 算法(在 Vue 中称之为 patch)是一种针对两颗虚拟 DOM 进行对比,查找其中的差异,然后根据差异性来更新页面的算法,其核心参考了 Snabbdom 原理。

diff 算法的特性:深度优先,同层级比较。

  • 只比较同一层级的标签,不跨级比较。
  • 如果同一层级的比较标签名不同,就直接移除老的虚拟 DOM 对应的节点,不继续按这个树状结构做深度比较。
  • 如果标签名相同,绑定的 key 属性的值也相同,就会认为是相同节点,也不继续按这个树状结构做深度比较。故在使用 v-for 遍历列表时,需要绑定一个 key 属性以提高遍历效率。