代码之家  ›  专栏  ›  技术社区  ›  Nina Lisitsinskaya

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

  •  1
  • Nina Lisitsinskaya  · 技术社区  · 7 年前

    我正在尝试使用虚拟用户.js2.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 在事件处理程序中获取 属性,但意识到我没有在函数模板中直接访问它们:

    TypeError: "_vm.$refs is undefined"
    

    那么,有没有一种方法可以访问一个本机HTML元素,在一个功能组件模板中创建一个附加到它的事件处理程序中的事件?我已经搜索了这个主题的文档,但是没有找到太多。

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

    0 回复  |  直到 7 年前
        1
  •  1
  •   esmekhov    7 年前

    你可以,但不是以预期的方式。关键是功能组件会将它们的ref传递到树上。因此,您的ref“input”将出现在包含函数复选框的组件中。如果您尝试在功能组件上附加ref-using模板,它将失败。

    所以呢 下面的方法行不通 (在父组件中),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

    推荐文章