javascript - 如何在 Vue.js 的功能组件模板中访问原生 HTML 元素?

标签 javascript vue.js vue-component stateless

我正在尝试使用 Vue.js 2.6 创建自定义复选框组件。我想让它成为无状态的,所以它以值作为 Prop ,并在用户输入时为父组件创建事件,并且它本身不保存任何数据。

这是我的单文件组件(简化版):

<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>

当 native 输入元素创建一个 input 事件时,我想将输入的 checked 属性传递给父组件监听器(如果存在)。

我尝试在事件处理程序中使用 $event.target.checked$refs.input.checked 来获取 checked属性,但意识到我无法在功能模板中直接访问它们:

TypeError: "_vm.$refs is undefined"

那么,有没有一种方法可以访问 native 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

关于javascript - 如何在 Vue.js 的功能组件模板中访问原生 HTML 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57000068/

相关文章:

javascript - 是否有纯 Javascript X/HTML 验证器?

javascript - Vue 组合 API 使用 VueAxios?

typescript - 在 Vue 组件上指定路由的正确方法

javascript - setTimeout方法,(交换组件)

javascript - 推送到组件页面Vue时的递归

javascript - 尝试退出循环,但目前仅继续循环 100 次

javascript - 使用 IFrame 在 jQuery 中进行事件传播

javascript - Air Datepicker - 用于突出显示的动态最小和最大日期

javascript - 将 Laravel 变量传递给 Vue.js

javascript - 如何从模板 vue.js 2 调用 javascript?