例子
父组件部分
<template>
<MyInput ref="inputRef" v-model="msg">
<template #append>
<div>append<div>
<template>
</MyInput>
</template>
<script setup>
import {ref} from "vue"
const inputRef = ref()
const msg = ref()
console.log(inputRef.value)
</script>
子组件部分
<template>
<component :is="h(ElInput,{...$attrs,...props,ref:changeRef})">
</component>
</template>
<script setup lang="ts">
import {ElInput ,type InputProps} from "element-plus"
import {getCurrentInstance,h} from "vue"
// 获取props
const props = defineProps<Partial<InputProps>>()
const vm = getCurrentInstance()
// ref也可以是一个函数
function changeRef(inputInstance){
// exposed 相当于defineEpose
vm. exposed = inputInstance || {}
// exposeProxy 代理对象
vm.exposeProxy = inputInstance || {}
}
</script>
component 的is属性也可以接收h函数渲染的组件
h 函数
- h 函数是一个用于创建虚拟 DOM 节点(VNode)的核心函数
h 函数的用处: - 动态生成内容:当你需要根据某些条件或数- 据动态生成 DOM 结构时,h 函数非常有用。
- 替代模板语法:在某些情况下,直接使用 JavaScript 编写模板比使用模板语法更灵活。
- 高阶组件:在编写高阶组件或渲染函数时,h 函数是必不可少的工具。
- JSX 支持:如果你在 Vue 中使用 JSX,h 函数会被隐式调用。
基本语法:
h(type, props, children)
参数说明:
1.type:
可以是一个 HTML 标签名(如 ‘div’),也可以是一个 Vue 组件。
例如:h(‘div’) 或 h(MyComponent)。
2.props(可选):一个对象,用于传递属性、事件监听器等。
例如:
h('button', {
onClick: () => console.log('Clicked!'),
class: 'btn'
}, 'Click me')
3.children(可选):
- 子节点,可以是字符串、数组(包含多个子节点)或其他 VNode。
例如:
h('div', null, [
h('span', null, 'Hello'),
h('span', null, 'World')
])
- 注意事项
h 函数必须在渲染函数或 setup 中使用
使用例子
基础用法
h(
'button',
{
onClick: () => alert('Button clicked!'),
class: 'btn'
},
'Click Me'
);
嵌套子节点
h(
'ul',
null,
items.map((item,index) => h('li', null, index))
);
动态组件
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
const currentComponent = ref('ComponentA');
const toggleComponent = () => {
currentComponent.value = currentComponent.value === 'ComponentA' ? 'ComponentB' : 'ComponentA';
};
h(
'div',
null,
[
h('button', { onClick: toggleComponent }, 'Toggle Component'),
h(currentComponent.value)
]
);
插槽
h(
Card,
null,
{
header: () => h('h1', null, 'Custom Header'),
default: () => h('p', null, 'This is the card content.'),
footer: () => h('small', null, 'Custom Footer')
}
);
这里的card也可以是h函数渲染的组件
import { defineComponent, h } from 'vue';
const Card = defineComponent({
setup(props, { slots }) {
return () => h(
'div',
{ class: 'card' },
[
slots.header ? slots.header() : h('div', null, 'Default Header'),
slots.default ? slots.default() : h('div', null, 'Default Content'),
slots.footer ? slots.footer() : h('div', null, 'Default Footer')
]
);
}
});
$attrs
在 Vue.js 中,子组件可以通过 $attrs 获取父组件传递的属性和方法
- $attrs 是一个对象,包含了父组件传递给子组件的所有非 props 和非 emits 的属性和事件监听器。
- 子组件可以通过 v-bind=“$attrs” 将这些属性和监听器传递给内部的子组件或元素。
例如:
<template>
<ChildComponent
title="Hello from Parent"
:count="42"
@custom-event="handleEvent"
/>
</template>
<script>
<template>
<div>
<p>Title: {{ $attrs.title }}</p>
<p>Count: {{ $attrs.count }}</p>
<button @click="$emit('custom-event', 'Hello from Child')">
Trigger Event
</button>
</div>
</template>
ref 接受函数的情况
如果传递给 ref
的是一个函数,Vue 会将该函数的返回值作为初始值。例如:
javascriptconst value = ref(() => {
console.log('Function called!');
return 42;
});
- 行为:
- 函数会被立即调用。
value.value
的值是函数的返回值(这里是42
)。- 函数内部的
console.log
会在初始化时执行一次。 - 返回的是一个静态值,不具备响应式依赖追踪
特性 | ref + 函数 |
computed |
---|---|---|
执行时机 | 初始化时调用一次 | 依赖变化时重新调用 |
响应性 | 无自动依赖追踪 | 自动追踪依赖 |
返回值 | 函数的返回值 | 动态计算的响应式值 |
适用场景 | 惰性初始化、复杂初始值 | 动态计算值 |