【问题标题】:How to access native HTML element in template of functional component in Vue.js?如何在 Vue.js 中访问功能组件模板中的原生 HTML 元素?
【发布时间】:2019-11-21 19:32:35
【问题描述】:

我正在尝试使用 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 元素,该元素创建一个事件,附加到它的事件处理程序中?我已经搜索了有关此主题的文档,但没有找到太多。

或者在这种情况下我应该只使用有状态组件吗?

【问题讨论】:

  • 您不能在模板内使用$refs。而是将所有逻辑移到组件声明中的方法中。
  • $event.target.checked 应该在任何v-on处理程序中工作
  • @Ohgodwhy 但是如何在功能组件的方法中访问 $refs?
  • @Phil 但在这种情况下我得到了TypeError: "_vm.$event is undefined" 错误。
  • 你能举例说明你是如何使用它的吗?

标签: javascript vue.js vue-component stateless


【解决方案1】:

您可以,但不是以预期的方式。问题在于它们将引用传递到树上的功能组件。因此,您的参考“输入”将出现在包含您的功能复选框的组件中。如果您尝试在功能组件上使用模板附加 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

【讨论】:

    猜你喜欢
    • 2017-05-10
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 2020-07-24
    • 2017-11-07
    • 1970-01-01
    相关资源
    最近更新 更多