【问题标题】:Vue Component, toggle dataVue 组件,切换数据
【发布时间】:2019-05-02 23:27:20
【问题描述】:

我觉得我快崩溃了,这是一些非常基本的东西,但它似乎不起作用......

基本上点击链接应该在真假之间切换display,但事实并非如此。

Vue.component('dropdown', {
    props: [ 'expanded' ],
    data: function() {
      return {
        display: !!(this.expanded)
      }
    },
    template: '<div><transition name="expand"><slot :display="display"></slot></transition></div>'
  });
  window.app = new Vue({
   el: '#app'
  });
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
    <dropdown>
      <div slot-scope="{ display }">
        <a href="javascript:void(0)" @click="display = !display">Toggle {{ display }}</a>
        <div v-if="display">
          Dropdown content
        </div>
      </div>
  </dropdown>
</div>

编辑:

更新的代码,我忘了我改变了,我确实有点击事件为display = !display。但是即使这样说,如果您尝试单击按钮,您会发现它也不会改变 true...

【问题讨论】:

  • @click="display = true" 总是将其设置为 true。 @click="display = !display",也许?
  • 您只需要@click="display = !display"
  • 根据您在现已删除的答案中的更新,尝试@click.prevent

标签: javascript vue.js


【解决方案1】:

thanksd 的更正评论后更新。我在没有真正理解的情况下偶然发现了正确的答案。

问题是在槽内,display 指的是作用域槽对象中的一个项目。在那里更新它不会更新实际的源变量。如果传入并调用函数,则会更新正确的变量。

Vue.component('dropdown', {
  props: ['expanded'],
  data: function() {
    return {
      display: Boolean(this.expanded)
    }
  },
  methods: {
    toggle() {
        this.display = !this.display;
    }
  },
  template: '<div><transition name="expand"><slot :display="display" :toggle="toggle"></slot></transition></div>'
});

new Vue({
  el: '#app'
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  <dropdown>
    <div slot-scope="{display, toggle}">
      <a href="javascript:void(0)" @click="toggle">Toggle {{ display }}</a>
      <div v-if="display">
        Dropdown content
      </div>
    </div>
  </dropdown>
</div>

【讨论】:

  • 我认为这是最好的解决方案,尽管如果您使用对象解构,就像 Martyn 在他的示例中所做的那样,没有必要命名作用域插槽对象。所以slot-scope="ss" 可能是slot-scope="{ display, toggle }"。答案的关键是添加toggle 方法并通过slot-scope 传递它允许父范围间接更新下拉组件实例的display 属性。 Martyn 示例的问题在于他正在更新作用域槽中变量的属性,这与更新实例上的相关属性不同。
  • 感谢@thanksd 澄清这一点。我已经相应地更新了我的答案。
  • 啊,现在说得通了,谢谢。我认为您可以直接从插槽内更改数据属性,因为我确信我以前在某处看到过这样做,但是我可能弄错了。我想直接影响它的唯一原因是避免在不需要时创建方法。
  • 如果数据属性是一个对象,您将能够更改其成员并将这些更改反映在源对象中(因为对象副本是别名)。
【解决方案2】:

一种解决方案是为dropdown 组件实现v-model,这将允许您将display 属性双向绑定到父级中的属性。这样你就不需要通过slot-scope 传递任何东西。

这是一个例子:

Vue.component('dropdown', {
  props: [ 'value' ],
  data() {
    return {
      display: !!(this.value)
    }
  },
  watch: {
    value(value) {
      this.$emit('input', value);
    }
  },
  template: '<div><transition name="expand"><slot></slot></transition></div>'
});

new Vue({
  el: '#app',
  data() {
    return { dropdownToggle: false }
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
    <dropdown v-model="dropdownToggle">
      <div>
        <a href="javascript:void(0)" @click="dropdownToggle = !dropdownToggle">
          Toggle {{ dropdownToggle }}
        </a>
        <div v-if="dropdownToggle">
          Dropdown content
        </div>
      </div>
  </dropdown>
</div>

【讨论】:

    猜你喜欢
    • 2016-08-20
    • 2020-09-20
    • 1970-01-01
    • 2018-07-07
    • 2019-01-23
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多