如何访问 Vue.js 功能组件模板中的原生 HTML 元素?
How to access native HTML element in template of functional component in Vue.js?
我正在尝试使用 Vue.js 2.6 创建自定义复选框组件。我想让它成为无状态的,所以它以值作为道具,并在用户输入时为父组件创建事件,并且本身不保存任何数据。
这是我的单文件组件(简化版):
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
functional: true,
props: {
value: {
type: Boolean,
default: false,
},
},
});
</script>
<template functional lang="pug">
label
input(type="checkbox" :checked="value" ref="input"
//-@input="(listeners['input'] || (() => {}))($refs.input.checked)")
@input="(listeners['input'] || (() => {}))($event.target.checked)")
</template>
生成此渲染函数的对象:
var render = function(_h, _vm) {
var _c = _vm._c
return _c("label", [
_c("input", {
ref: "input",
attrs: { type: "checkbox" },
domProps: { checked: _vm.value },
on: {
input: (_vm.listeners["input"] || function() {})(
//_vm.$refs.input.checked
_vm.$event.target.checked // Got error on this line
)
}
})
])
}
var staticRenderFns = []
render._withStripped = true
父组件:
<template lang="pug">
form
checkbox(:value="value" @input="value = $event")
//-checkbox(v-model="value") - also should work
</template>
<script lang="ts">
import Vue from 'vue';
import { default as Checkbox } from './checkbox.vue';
export default Vue.extend({
components: {
checkbox: Checkbox,
},
data() {
return { value: false };
},
});
</script>
当本机输入元素创建一个input
事件时,我想将输入的checked
属性传递给父组件侦听器(如果存在)。
我尝试在事件处理程序中使用 $event.target.checked
和 $refs.input.checked
来获取 checked
属性,但意识到我无法直接访问它们在功能模板中:
TypeError: "_vm.$refs is undefined"
那么,有没有一种方法可以访问本机 HTML 元素,该元素会在功能组件模板中创建一个附加到事件处理程序的事件?我搜索了有关此主题的文档,但没有找到太多内容。
或者在这种情况下我应该只使用有状态组件吗?
可以,但不是以预期的方式。问题在于功能组件,它们将引用向上传递到树中。因此,您的 ref 'input' 将出现在包含您的功能复选框的组件中。如果您尝试在您的功能组件上使用模板附加 ref,它只会失败。
所以 下面的内容不起作用(在你的父组件中),ref 'check' 不会在那里。但是 ref 'input' 至少是最后一个,如果你放了多个复选框。
<form>
<functional-checkbox ref="check" :value="myValue" @input="myValue = $event"/>
</form>
但是下面会
<form>
<functional-checkbox :value="myValue" @input="myValue = $event"/>
</form>
// later in code (assuming functional-checkbox has ref="input" defined inside)
this.$refs.input // will have a value, when the component is _mounted_
关于功能性复选框组件的问题 - 有一个更简单的修复方法。您只需要将处理程序定义为函数调用 ,因为 Vue 模板编译器可以理解它。它并不完美,这就是为什么尽管您已经创建了一个函数调用,但它并没有被这样解释。
所以你需要像这样简化你的函数调用
<template functional>
<label>
<input type="checkbox" :checked="props.value"
@input="listeners.input && listeners.input($event.target.checked)">
</label>
</template>
这将被解释为所需的
var render = function(_h, _vm) {
var _c = _vm._c
return _c("label", [
_c("input", {
attrs: { type: "checkbox" },
domProps: { checked: _vm.props.value },
on: {
input: function($event) {
_vm.listeners.input && _vm.listeners.input($event.target.checked)
}
}
})
])
}
如果你对这个渲染函数到底是怎么来的感兴趣的话,你可以在这里看得更详细
https://github.com/vuejs/vue/blob/dev/packages/vue-template-compiler/browser.js#L4169
我正在尝试使用 Vue.js 2.6 创建自定义复选框组件。我想让它成为无状态的,所以它以值作为道具,并在用户输入时为父组件创建事件,并且本身不保存任何数据。
这是我的单文件组件(简化版):
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
functional: true,
props: {
value: {
type: Boolean,
default: false,
},
},
});
</script>
<template functional lang="pug">
label
input(type="checkbox" :checked="value" ref="input"
//-@input="(listeners['input'] || (() => {}))($refs.input.checked)")
@input="(listeners['input'] || (() => {}))($event.target.checked)")
</template>
生成此渲染函数的对象:
var render = function(_h, _vm) {
var _c = _vm._c
return _c("label", [
_c("input", {
ref: "input",
attrs: { type: "checkbox" },
domProps: { checked: _vm.value },
on: {
input: (_vm.listeners["input"] || function() {})(
//_vm.$refs.input.checked
_vm.$event.target.checked // Got error on this line
)
}
})
])
}
var staticRenderFns = []
render._withStripped = true
父组件:
<template lang="pug">
form
checkbox(:value="value" @input="value = $event")
//-checkbox(v-model="value") - also should work
</template>
<script lang="ts">
import Vue from 'vue';
import { default as Checkbox } from './checkbox.vue';
export default Vue.extend({
components: {
checkbox: Checkbox,
},
data() {
return { value: false };
},
});
</script>
当本机输入元素创建一个input
事件时,我想将输入的checked
属性传递给父组件侦听器(如果存在)。
我尝试在事件处理程序中使用 $event.target.checked
和 $refs.input.checked
来获取 checked
属性,但意识到我无法直接访问它们在功能模板中:
TypeError: "_vm.$refs is undefined"
那么,有没有一种方法可以访问本机 HTML 元素,该元素会在功能组件模板中创建一个附加到事件处理程序的事件?我搜索了有关此主题的文档,但没有找到太多内容。
或者在这种情况下我应该只使用有状态组件吗?
可以,但不是以预期的方式。问题在于功能组件,它们将引用向上传递到树中。因此,您的 ref 'input' 将出现在包含您的功能复选框的组件中。如果您尝试在您的功能组件上使用模板附加 ref,它只会失败。
所以 下面的内容不起作用(在你的父组件中),ref 'check' 不会在那里。但是 ref 'input' 至少是最后一个,如果你放了多个复选框。
<form>
<functional-checkbox ref="check" :value="myValue" @input="myValue = $event"/>
</form>
但是下面会
<form>
<functional-checkbox :value="myValue" @input="myValue = $event"/>
</form>
// later in code (assuming functional-checkbox has ref="input" defined inside)
this.$refs.input // will have a value, when the component is _mounted_
关于功能性复选框组件的问题 - 有一个更简单的修复方法。您只需要将处理程序定义为函数调用 ,因为 Vue 模板编译器可以理解它。它并不完美,这就是为什么尽管您已经创建了一个函数调用,但它并没有被这样解释。
所以你需要像这样简化你的函数调用
<template functional>
<label>
<input type="checkbox" :checked="props.value"
@input="listeners.input && listeners.input($event.target.checked)">
</label>
</template>
这将被解释为所需的
var render = function(_h, _vm) {
var _c = _vm._c
return _c("label", [
_c("input", {
attrs: { type: "checkbox" },
domProps: { checked: _vm.props.value },
on: {
input: function($event) {
_vm.listeners.input && _vm.listeners.input($event.target.checked)
}
}
})
])
}
如果你对这个渲染函数到底是怎么来的感兴趣的话,你可以在这里看得更详细 https://github.com/vuejs/vue/blob/dev/packages/vue-template-compiler/browser.js#L4169