4.API
4.1. 全局API
通过 Vue 调用 的 就是全局 api, 如前面的 Vue.component()
4.1.1.Vue.directive 自定义指令
Vue.js 中的 Vue.directive
是 Vue 提供的一种自定义指令(Directives)的功能。
自定义指令允许开发者扩展 HTML 元素的功能,为其绑定特殊的响应式行为。
创建一个自定义指令的基本格式如下:
Vue.directive('指定名', {
钩子函数(el, binding, vnode){}
});
4.1.1.1.常用钩子函数
- bind
- 在指令第一次绑定到元素上时调用。可以在这里执行一次性初始化设置。
- 参数:
el
(绑定元素),binding
(一个对象,包含指令的各种信息,如值、旧值、参数、修饰符等),vnode
(Vue编译生成的虚拟节点)。
- inserted
- 当元素被插入到父节点时调用(仅保证父节点存在,但不保证元素已插入到文档流中)。
- 参数与
bind
相同。
- update
- 当指令所在组件的 VNode 更新时调用,指令的值可能发生了变化。
- 参数与
bind
相同。
- componentUpdated
- 当指令所在组件的 VNode 以及其子 VNode 完全更新后调用。
- 参数与
bind
相同。
- unbind
- 只调用一次,指令与元素解绑时调用。
- 参数与
bind
相同。
钩子函数的参数
el
:指令所绑定元素的真实 DOM 对象。binding
:一个对象,包含以下属性:value
:指令的绑定值,可读可写。oldValue
:上一次指令绑定值,在update
钩子中可用。arg
:指令的参数,如果在指令使用时指定了参数(如v-my-directive:foo
,则arg
为"foo"
)。modifiers
:一个对象,包含指令的修饰符,如v-my-directive.modifier
中的modifier
。
vnode
:Vue 编译生成的虚拟节点。
4.1.1.2.实例一: 使元素背景色随时间变换:
Vue.directive('color-change', {
bind(el, binding) {
el.style.backgroundColor = binding.value;
const intervalId = setInterval(() => {
el.style.backgroundColor = getRandomColor(); // 假设有个函数能生成随机颜色
}, 1000);
// 在解绑指令时清除定时器
el._intervalId = intervalId;
},
unbind(el) {
clearInterval(el._intervalId);
},
});
new Vue({
// ...
});
在模板中使用自定义指令:
<div v-color-change="'red'"></div>
这样,v-color-change
指令就会被应用到 div 元素上,并在绑定时设置初始背景色,然后每隔一秒更改一次背景色。当 Vue 实例销毁或指令解除绑定时,定时器会被清理。
4.1.1.3.实例二: 获得焦点:
<body>
<div id="app">
<input type="text" v-focus="true" name="" id="" value="" />
</div>
</body>
<script type="text/javascript">
// 自定义 focus 指令
Vue.directive("focus",{
// el: 当前绑定的元素 binding : 指令本身
inserted(el, binding){
if(binding.value){
el.focus();
}
}
})
var vm= new Vue({el:"#app"})
</script>
**4.1.2.Vue.use 安装插件
Vue.use()
是用于安装 Vue 插件或者其他 Vue 兼容的库。
当你开发或者使用一个遵循 Vue 插件规范的第三方模块时,通常会通过这个方法将其注册到 Vue 上。
如: 在项目中 引入 ElementUI时
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'; // 引入默认主题样式
Vue.use(ElementUI); // 注册 Element UI 到 Vue 的原型上
4.1.2.1.自定义插件时
插件可以是一个对象或函数
如果是对象,必须提供 install()方法, 来安装插件
而函数将被当成 install()方法
<body>
<div id="app" v-my-directive ></div>
</body>
<script type="text/javascript">
// 定义一个MyPlugin(自定义插件)对象
let MyPlugin = {}
// 对象的 install() 方法
MyPlugin.install = function(Vue, options){
console.log(options)
// 在插件中为Vue添加自定义指令
Vue.directive("my-directive", {
bind(el, binding){
// 为绑定元素 设置 样式
el.style = "width:100px;height:100px;background-color:#ccc;"
}
})
}
Vue.use(MyPlugin, {someOption: true})
var vm = new Vue({el:"#app"})
</script>
4.1.3.Vue.extend
Vue.extend()
是用于创建一个 Vue 组件的构造器。
这个构造器继承自 Vue,允许我们基于 Vue 的原型方法和属性创建一个子类,
并可以在子类中定义额外的选项,如组件的模板、数据、方法、生命周期钩子等。
基本语法:
const ExtendedVue = Vue.extend(options)
options
:这是一个对象,包含 Vue 组件的选项,如data
、methods
、computed
、template
或render
函数等。
使用 Vue.extend()
创建的构造器可以用来生成 Vue 组件实例,这在动态组件或者需要多次复用相同配置的场景中特别有用。
示例:
const MyComponent = Vue.extend({
template: '<p>{{ message }}</p>',
data() {
return {
message: 'Hello from extended Vue instance!'
}
}
});
// 创建并挂载一个组件实例
new MyComponent().$mount('#app');
此外,Vue Router 和 Vuex 在创建组件时也会经常用到 Vue.extend()
,以确保生成的组件具有完整的 Vue 生态系统支持。
**4.1.4.Vue.set
Vue.set()
主要用于响应式地向现有对象上添加新的属性或修改已存在的属性值,并确保这些改变能够触发视图更新。
由于 Vue 使用了基于 getter 和 setter 的观察系统来实现数据绑定和反应性,
直接通过 JavaScript 的点操作符(.
)或索引操作符([]
)对对象属性进行增加或修改时,
新增的属性可能不会被 Vue 系统跟踪,因此不会触发相应的视图更新。
Vue的核心具有一套响应式系统,简单来说就是通过监听器监听数据层的数据变化,当数据改变后,通知视图也自动更新。
Vue.set用于向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。
4.1.4.1.基本语法
Vue.set()
方法的用法如下:
Vue.set(target, key, value)
target
: 需要更改的对象,即你想要在其上添加或修改属性的对象。key
: 要添加或修改的属性名。value
: 要赋予新属性的值,或者是要更新的已有属性的新值。
例如:
let vm = new Vue({
data: {
user: {
name: '王小二'
}
}
})
// 直接添加新属性不会触发视图更新
vm.user.age = 30; // 这里不响应
// 使用 Vue.set 添加新属性会触发视图更新
Vue.set(vm.user, 'age', 30);
4.1.4.2.更新数组
// 对于数组,也可以使用 Vue.set 来响应式地向指定索引添加元素
vm.someArray = []
Vue.set(vm.someArray, 0, '新增元素');
另外,对于数组而言,Vue 还提供了 vm.$set()
实例方法,它与 Vue.set()
功能相同,但可以直接在实例上下文中调用:
vm.$set(vm.someArray, 0, '新增元素');
4.1.5.Vue.mixin
Vue.mixin()
是 用于向 Vue 的所有组件实例注入全局混合(mixin)选项。
混合是一种在多个组件间复用共同功能的方式,它可以包含任意数量的组件选项,如数据、计算属性、方法、生命周期钩子等。
Vue.mixin用于全局注册一个混入(Mixins), 它将影响之后创建的每个Vue实例。
该接口主要是提供给插件作者使用,在插件中向组件注入自定义的行为。
该接口不推荐在应用代码中使用。使用Vue.mixin为Vue实例注入created()函数。
使用 Vue.mixin()
的基本语法如下:
Vue.mixin({
data() {
return {
mixinData: '混合的数据.'
}
},
methods: {
mixinMethod() {
console.log('混合的方法.');
}
},
created() {
console.log('混合创建完成.');
},
// ... 其他组件选项
});
一旦定义了一个混合,它会被注入到每个新的 Vue 组件实例中,无论何时创建这些组件。
这意味着混合中的所有选项都会合并到组件的选项中,如果有冲突(例如,组件本身和混合中都定义了同名的数据属性或方法),组件本身的选项优先级更高。
需要注意的是,过度使用全局混合可能会让项目变得难以理解和维护,因为它会影响到每个 Vue 组件,建议谨慎使用,
并尽量将其限制在必要的情况下,比如全局状态管理和工具函数封装等。
在团队协作中,明确指出哪些组件受到了全局混合的影响也非常重要。
4.2.实例属性和方法
Vue.js 中以 $
开头的属性和方法通常表示它们是Vue框架提供的内置属性或方法,旨在帮助开发者更好地管理和操作Vue实例。
4.2.1.实例属性
4.2.1.1.vm.$root
获取当前组件树的根Vue实例, 没有父实例,就是当前实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<child></child>
</div>
</body>
<script>
Vue.config.productionTip = false
// 子组件
let child = Vue.extend({
template: `<div>
<button @click="accessRootData">操作根数据</button>
</div>`
,methods: {
accessRootData() {
console.log(this.$root.globalMessage); // 输出: "Hello from root!"
}
}
})
new Vue({
el: '#app',
data:{
globalMessage: '全局消息!'
},
components: {
child
}
})
</script>
</html>
4.2.1.2.vm.$el
指向Vue实例关联的DOM元素,即Vue实例挂载的根DOM节点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
hello world
</div>
</body>
<script>
Vue.config.productionTip = false
new Vue({
el: '#app',
mounted() {
console.log(this.$el); // 输出当前组件的根DOM元素
this.$el.style.color = 'red'; // 直接修改当前组件内所有文本的颜色为红色
}
})
</script>
</html>
4.2.1.3.vm.$options
获取在vue实例初始化时, 传入的自定义的选项( 选项值 可以是 数组,对角,函数),
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{message}}
</div>
</body>
<script>
Vue.config.productionTip = false
new Vue({
el: '#app',
data() {
return {
message: 'Hello Vue!'
}
},
created() {
console.log(this.$options.data()); // 输出此组件的data配置
}
})
</script>
</html>
4.2.1.4.vm.$data
引用Vue实例的数据对象,可以直接访问所有数据属性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{message}}
</div>
</body>
<script>
Vue.config.productionTip = false
new Vue({
el: '#app',
data() {
return {
message: 'Hello Vue!'
}
},
created() {
console.log(this.$data.message); // 输出: "Hello Vue!"
this.$data.message = '更新 message'; // 在 页面模板中更新 message 的值
}
})
</script>
</html>
4.2.1.5.vm.$props
包含了父组件传递给当前组件的所有props。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<div id="app">
<child :message="globalMessage"></child>
</div>
</body>
<script>
Vue.config.productionTip = false
// 子组件
let child = Vue.extend({
template: `<div>
{{message}}
</div>`,
props: {
message: String
},
mounted() {
console.log(this.$props.message); // 输出: "父组件消息!"
}
})
new Vue({
el: '#app',
data:{
globalMessage: '父组件消息!'
},
components: {
child
}
})
</script>
</html>
4.2.1.6.vm.$attrs
获取当前组件的属性, 不包含 class, style以及被声明为props的属性
(不包括class
和style
,这两个特殊属性会被合并并分别暴露为$attrs.class
和$attrs.style
)。
$attrs
主要用于传递那些并非专门针对当前组件设计,而是希望其进一步向下传递给子孙组件的属性集合。- 子组件可以通过
v-bind="$attrs"
将其继承的所有非props属性进一步传递给自己的后代组件。
4.2.1.7.vm. p a r e n t / v m . parent /vm. parent/vm.children
分别指父组件实例和当前组件的直接子组件实例数组。 但不保证顺序, 也不是响应式的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<div id="app">
<child :message="globalMessage"></child>
</div>
</body>
<script>
Vue.config.productionTip = false
// 子组件
let child = Vue.extend({
template: `<div>
{{message}}-{{childMessage}}
</div>`,
props: {
message: String
},
data() {
return {
childMessage: '子组件消息!'
}
},
mounted() {
console.log(this.$parent.parentMessage ); // 输出:
}
})
new Vue({
el: '#app',
data:{
globalMessage: '父组件消息!',
parentMessage: 'parent消息!'
},
mounted() {
console.log(this.$children[0].childMessage);
},
components: {
child
}
})
</script>
</html>
4.2.1.8.vm. s l o t s / v m . slots / vm. slots/vm.scopedSlots
包含所有被分配给当前组件的插槽内容 / 包含作用域插槽函数的对象
***4.2.1.9.vm.$refs
根据元素的 ref属性 , 获取元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" ref="inp" value="hello" />
</div>
</body>
<script>
Vue.config.productionTip = false
new Vue({
el: '#app',
mounted() {
console.log(this.$refs.inp.value); // 输出 : hello
}
})
</script>
</html>
4.2.2.实例方法
4.2.2.1.$watch
用于监听Vue实例上的数据变化。
4.2.2.2.$set
设置响应式属性,确保即使在对象上新增属性也能触发视图更新。
4.2.2.3.$delete
删除响应式对象的属性,并确保视图同步更新。
***4.2.2.4.$emit
触发当前组件实例上的自定义事件。
4.2.2.5.$on / $off / $once
用于监听和移除自定义事件监听器。
4.2.2.6.$nextTick
在下次DOM更新循环结束之后执行延迟回调,在修改数据之后可以使用它来等待DOM更新完毕。
例如,当你需要在更改数据后立即做某些依赖于DOM的操作时,由于Vue.js是异步更新DOM的,直接在数据更改后操作DOM可能无效,因为DOM尚未更新。这时可以使用$nextTick
:
<body>
<div id="app">
<h1 ref="hh" >{{ msg }}</h1>
<button @click="edit">修改</button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue!'
},
methods: {
edit(){
this.msg = "你好, 王小二"
console.log( "1", this.$refs.hh.innerHTML ) // 此时 DOM 还没有渲染更新, 所以打印为 Hello Vue!
this.$nextTick(function () {
console.log( "2", this.$refs.hh.innerHTML ) // DOM渲染更新后, 执行这段代码 打印 你好, 王小二
})
}
}
})
</script>
$nextTick
接收一个回调函数作为参数,这个回调将在DOM更新之后(微任务队列中)执行,确保了在回调执行时,Vue已经完成了对视图的更新。
4.2.2.7.$forceUpdate
强制立即重新渲染整个组件,无视虚拟DOM的优化。
4.2.2.8.vm.$destroy
用于手动销毁一个 Vue 组件实例。当调用该方法时,Vue 会执行以下操作:
- 解除所有的自 事件监听器和指令绑定。
- 删除所有的子组件实例。
- 删除所有与之相关的
$watch
监听。 - 清除 Vue 实例上的
$el
属性,使其脱离DOM,避免内存泄漏。
4.3.全局配置 config
4.3.1.productionTip
当在网页中加载了vue.js(开发版本)文件时,浏览器的控制台会出现英文的提示信息,提醒用户“您正在开发模式下运行Vue,在为生产部署时,请确保打开生产模式”。如果要打开生产模式,使用vue.min.js文件代替vue.js文件即可。
You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
或者 (但 测试没好使)
<script>
Vue.config.productionTip=false
</script>
4.3.2.silent
Vue全局配置对象中,silent可以取消Vue日志和警告,值类型为boolean,默认值为false,设为true表示忽略警告和日志,否则不忽略。
4.3.3.devtools
设置是否启用 浏览器web调试工具
4.4.组件强化
4.4.1.mixins 混入
mixins是一种分发Vue组件中可复用功能的方式。
mixins对象可以包含任何组件选项,当组件使用mixins时,将定义的mixins对象引入组件中即可使用,
mixins中的所有选项将会混入到组件自己的选项中。
var myMixin = {
created(){
this.hello()
},
methods: {
hello(){
console.log("hello from mixin!")
}
}
}
var Component = Vue.extend({
mixins:[myMixin]
})
var compent = new Component()
**4.4.2.render 渲染
在 Vue.js 中,render
函数是一种高级的组件定制方式,用于取代传统的模板。
在Vue中一般使用template来创建HTML, 但这种方式可编程性不强,而使用Vue.render()可以更好地发挥JavaScript的编程能力。
它接受一个函数,该函数需要返回一个虚拟 DOM 树(VNode),Vue.js 内部会根据 VNode 和实际 DOM 的差异进行高效的 DOM 更新。
4.4.2.1.案例一
export default {
render(createElement) {
return createElement('div', {}, [
createElement('h1', {}, '标题'),
createElement('p', {}, '内容')
]);
}
}
在这个例子中,render
函数返回了一个包含 h1
和 p
元素的 div
元素的虚拟 DOM。createElement
函数(在 Vue 2.x 中可能是 this.$createElement
或外部导入的 createElement
函数)用于创建虚拟 DOM 节点,其参数依次为:
- 元素标签名(如
'div'
、'h1'
、'p'
); - 一个对象,用于定义元素的属性、样式、事件等(如
{}
或{ class: ['container'] }
); - 子节点数组,可以是更多的虚拟 DOM 节点,也可以是纯文本(如
['内容']
)。
使用 render
函数的优势在于它具有更高的灵活性和更好的性能优化潜力,特别是在需要大量动态渲染逻辑、组件递归渲染、直接操作DOM节点或者集成第三方库(如D3.js)等场景中。
然而,相比于模板,render
函数的可读性和维护性相对较低,一般情况下,除非有特殊需求,否则推荐优先使用模板语法。
4.4.2.2.案例二
<body>
<div id="app">
<my-component>成功渲染</my-component>
</div>
</body>
<script type="text/javascript">
Vue.component("my-component", {
render(createElement){
return createElement('p', {
style:{
color:"red",
fontSize: "16px",
backgroundColor: "#eee"
}
}, this.$slots.default)
}
})
var vm = new Vue({el:"#app"})
</script>
4.4.3.createElement 创建元素
createElement
函数在 Vue 2.x 版本中作为底层方法存在,用于创建虚拟DOM节点。然而,在 Vue 3.x 中,这个方法被重命名为 h
。
用于创建 Vue 组件的虚拟节点,它是 Vue 渲染函数的基础,常用于编写渲染函数(Render Function)替代传统的模板。
渲染函数可以返回虚拟DOM节点,Vue.js 内部会根据虚拟DOM和实际DOM的差异进行高效的DOM更新。
create Element()函数的参数
第1个参数可以是一个HTML标签名或组件选项对象;
第2个参数是可选的,可以传入一个与模板中属性对应的数据对象;
第3个参数是由 createElement()构建而成的子级虚拟节点,也可以使用字符串来生成文本虚拟节点,具体可以参考Vue的官方文档。
4.4.3.1.实例一
import { createElement } from 'vue'
export default {
render(createElement) {
return createElement(
'div', // 标签名
{
class: ['container'], // 属性
on: { click: this.handleClick } // 事件监听器
},
[ // 子节点数组
createElement('span', 'Hello'),
this.message ? createElement('p', this.message) : null
]
)
},
methods: {
handleClick() {
// ...
}
}
}
4.4.3.2.虚拟DOM
createElement()函数返回的并不是一个实际的DOM元素,它返回的其实是一个描述节点(createNodeDescription),
用来告诉Vue在页面上需要渲染什么样的节点。
这个描述节点也可以称为虚拟节点(Virtual Node),简写为VNode。
而“虚拟DOM”是对由Vue 组件树建立起来的整个 VNode 树的称呼。
4.4.3.3.实例二
<body>
<div id="app">
<my-component>
<template v-slot:header >
<div style="background-color: #CCCCCC;height: 50px;">
这里是导航栏
</div>
</template>
<template v-slot:content >
<div style="background-color: #DDDDDD;height: 50px;">
这里是展示信息
</div>
</template>
<template v-slot:footer >
<div style="background-color: #EEEEEE;height: 50px;">
这里是底部信息
</div>
</template>
</my-component>
</div>
</body>
<script type="text/javascript">
Vue.component('my-component',{
render(createElement){
return createElement('div',[
createElement('header', this.$slots.header),
createElement('content', this.$slots.content),
createElement('footer', this.$slots.footer),
])
}
})
var vm = new Vue({el: "#app"})
</script>