Vue.js 前端开发实战之 04-Vue 开发基础(3)
全局 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 属性以提高遍历效率。