当一个组件需要分多个参数传递 props 值的时候,而这些参数又刚好是某个对象的属性
<template>
<User
:name="user.name"
:avatar="user.avatar"
:email="user.email"
/>
template>
这个时候可以直接通过v-bind
绑定对象来将它的属性值作为 props 自动传递给组件
<template>
<User v-bind="user"/>
template>
export default {
setup() {
return {
user: {
name: 'Timfan',
avatar: 'my-profile.jpg',
email: '[email protected]'
}
}
}
};
这种用法同样也适用于通过 v-on
来绑定多个事件监听器
<template>
<User v-on="userEventHandlers"/>
template>
export default {
setup() {
return {
userEventHandlers: {
updateName(newName) {
// ...
},
deleteUser() {
// ...
},
addFriend(friend) {
// ...
}
}
}
}
};
不知道你是否有这样的疑惑,当你在使用侦听器 watch
的时候,发现侦听的对象变化并没有正确地触发回调函数,通常这是因为侦听的对象是一个数组或者对象,但是没有设置deep
的值为true
造成的。
export default {
name: 'ColourChange',
props: {
colours: {
type: Array,
required: true,
},
},
watch: {
// Use the object syntax instead of just a method
colours: {
// This will let Vue know to look inside the array
deep: true,
// We have to move our method to a handler field
handler(oldVal, newVal)
console.log('The list of colours has changed!');
}
}
}
}
同理在 Vue 3 中使用的是响应式 API 来实现的,方式如下
watch(
colours,
() => {
console.log('The list of colours has changed!');
},
{
deep: true,
}
);
详细用法可以参考官方文档 https://cn.vuejs.org/guide/essentials/watchers.html
我们可以在 Props 的定义项里通过validator
属性来传递一个回调来为它的值做校验
export default {
name: 'Image',
props: {
src: {
type: String,
},
style: {
type: String,
validator: s => ['square', 'rounded'].includes(s)
}
}
};
这个校验函数根据值是否有效,返回true
或者false
两种值。
通常按钮组件或者提示组件的类型(诸如:“info”, “success”, “danger”, “warning”)需要使用到该种用法作为有效值校验。这只是其中一种,还有更多的使用场景。
当你注册一个全局组件,你就不再需要进行第二次导入就可以在 template
中使用:
/ Vue 3
import { createApp } from 'vue';
import GlobalComponent from './GlobalComponent.vue';
const app = createApp({})
app.component('GlobalComponent', GlobalComponent);
在 Vue 2 中采用如下方案
// Vue 2
import Vue from 'vue';
import GlobalComponent from './GlobalComponent.vue';
Vue.component('GlobalComponent', GlobalComponent);
现在你可以在项目中的任何 template
中使用 GlobalComponent
全局组件,不需要进行额外的处理。当然全局组件和全局变量有着同样的利弊,请谨慎使用。
也许你之前没见过,但是确实可以直接通过引号括起来监听嵌套的值,特别在深层嵌套的情况下,特别方便。
watch: {
'$route.query.id'() {
// ...
}
}
事实上组件中的任何响应式的变量都是可以通过watch
来监听的:
export default {
computed: {
someComputedProperty() {
// Update the computed prop
},
},
watch: {
someComputedProperty() {
// Do something when the computed prop is updated
}
}
};
只要这个值是ref
或reactive
转化的响应式对象,或者是computed
实现的计算属性值,你都可以通过watch
来监听它的变化。
h
和 Render
函数当我们使用render
函数来代替template
模板的时候,通常是通过h
函数来实现的:
<script setup>
import { h } from 'vue';
const render = () => h('div', {}, 'Hello Wurld');
</script>
它的作用是创建了一个虚拟节点,一个 Vue 内部跟踪变化的对象和最终渲染到页面中的文本。
第一个参数也就是这个虚拟节点可以是任意的 HTML 元素,也可以是封装好的可以调用的 Vue 组件
<script setup>
import { h } from 'vue';
import MyComponent from './MyComponent.vue';
const render = () => h(MyComponent, {}, []);
</script>
第二个参数可以是一系列的props
值,自身的属性,或者事件监听器
<script setup>
import { h } from 'vue';
import MyComponent from './MyComponent.vue';
const render = () => h(MyComponent, {
class: 'text-blue-400',
title: 'This component is the greatest',
onClick() {
console.log('Clicked!');
},
}, []);
</script>
第三个参数可以是一串文本,一个子节点组成的数组,或者用来定义slot
的对象
h
函数的使用为我们带来通过 javaScript 复杂的逻辑创建 html 的便利性。
在开发中我们可以在页面路由中携带参数,这对于我们进入到某个页面预设一些操作是很有用的,比如进入到某个有默认选项的页面或者需要滚动到某个位置,都可以通过获取到路由中的参数值来达到。
const dateRange = this.$route.query.dateRange;
这对于分离的两个不同的应用之间的通信也是通过该原理实现的。
我们很熟悉在 template 模板中使用自定义指令的方式,直接通过 v-指令名
,而 Vue 提供了resolveDirective
和withDirectives
两个接口,前者可以获取到自定义的指令添加到第二个接口的回调参数中
<script setup>
import { resolveDirective, withDirectives, h } from 'vue';
// Find the already registered directive by name
const focusDirective = resolveDirective('focus');
// Wrap the button with the directive
const render = () => withDirectives(
h('button', {}, []),
// An array of directives to apply
[
[focusDirective]
]
);
</script>
我们如何在 Vue 应用中自定义在 html 中可以使用的元素,可以分三步完成:
第一步:通过 Vue 提供的接口defineCustomElement
import { defineCustomElement } from 'vue';
import MyVueComponent from './MyVueComponent.vue';
const customElement = defineCustomElement(MyVueComponent);
第二步:注册自定义元素到 DOM 中:
customElements.define('my-vue-component', customElement);
第三步:在 HTML 结构中直接使用该自定义元素
<html>
<head>head>
<body>
<my-vue-component>my-vue-component>
body>
html>
这样就实现了一个不需要任何框架就可以在浏览器中运行的自定义组件( 也就是通常说的 Web Component)。
当我们通过$ref
来访问某个组件的时候,我们是无法直接访问组件内部的方法或者属性变量的
export default {
expose: ['makeItPublic'],
data() {
return {
privateData: 'Keep me a secret!',
};
},
computed: {
makeItPublic() {
return this.privateData.toUpperCase();
},
},
};
但是 Vue 提供的 expose 可以将内部的属性或方法暴露出来供外部使用,这里可以访问makeItPublic
方法
this.$refs.component.makeItPublic()
在 Vue3 中当我们使用