【问题标题】:Changing vue instance variables from within component从组件内更改 vue 实例变量
【发布时间】:2018-10-01 21:12:09
【问题描述】:

我一直在自学 Vue.js,并一直在利用组件来增加模块化。

我正在努力解决的一件事是从组件内部操作 Vue 实例中的变量。通过将翡翠文件中的变量作为道具传递,我已经让它在组件内与v-model 很好地配合

例如loginform(slot="login-form" v-bind:form-submit="loginSubmit" v-bind:login-data="loginData")

其中 loginData 包含变量用户名和密码,它们是组件内输入的'v-modelled'。然后在组件模板中:

<input type="password" class="text-field" v-model="formData.password" />

但是,我有一个工具提示组件,我想使用两次:一个用于用户名字段,另一个用于密码字段。这些工具提示的可见性分别由tooltips.username.vistooltips.password.vis 给出。

尽管组件中的v-model 没有发出这些警告,但我似乎无法将该变量作为道具传递以便在没有得到avoid manipulating props 警告的情况下进行操作。工具提示组件如下:

Vue.component('tooltip', {
  props: ['show', 'message', 'click'],
  template:
    <transition name="shrink">
      <div v-show="show" v-on:click="click" class="tooltip">
        <div class="tooltip-arrow"></div>
        <div class="tooltip-container">{{message}}</div>
      </div>
    </transition>
}); 

有没有人知道如何实现所需的效果(在鼠标单击时隐藏工具提示)。我尝试将一个方法作为 click 属性传递,该方法根据工具提示是用于用户名还是密码输入而具有不同的参数,但是我得到了单击未定义的警告。我可以创建两个单独的函数,但我宁愿不明确编写两个做同样事情的函数。

【问题讨论】:

  • 您的用户名/密码v-model 不会发出警告,因为您正在为道具传递一个对象,然后更新该对象中的属性。道具仍然引用同一个对象。如果你在没有包装对象的情况下传递它们,你会看到同样的警告。
  • @skirtle 啊谢谢!您刚刚回答了我对以下答案的评论。感谢您的澄清:)

标签: javascript vue.js vue-component


【解决方案1】:

您不应该尝试从组件内修改 props,因为 Vue 的警告告诉您,对 props 的更改不会从组件流向 props,因此任何更改都将被覆盖。

对于您想要实现的目标,您应该查看 Vue 的自定义事件 https://vuejs.org/v2/guide/components-custom-events.html

HTML

<div id="app">
   <form>
        <div>
           <label>Username</label>
           <input type="username" v-model="formData.username" />
           <tooltip :show="tooltips.username.vis" 
    :message="tooltips.username.message" @tooltip:hide="tooltips.username.vis = false" />
        </div>

        <div>
           <label>Password</label>
           <input type="text" v-model="formData.password" />
           <tooltip :show="tooltips.password.vis" 
   :message="tooltips.password.message" @tooltip:hide="tooltips.password.vis = false" />
        </div>
   </form>
</div>

JS

Vue.component('tooltip', {
  props: ['show', 'message'],
  template: `<transition name="shrink">
      <div v-show="show" class="tooltip" @click="hide">
        <div class="tooltip-arrow"></div>
        <div class="tooltip-container">{{message}}</div>
      </div>
    </transition>`,
  methods: {
    hide () {
      this.$emit('tooltip:hide');
    },
  }
}); 

new Vue({
    el: "#app",
    data: {
      formData: {
        username: '',
        password: ''
      },
      tooltips: {
        username: {
            message: 'Fix your username',
            vis: true
        },
        password: {
            message: 'Fix your password',
            vis: true
        }
    }
    }
});

https://jsfiddle.net/10fjkoob/12/

【讨论】:

  • 哦,谢谢你完美的回答。我只是事先注意到,当我直接将可见性变量(tooltips.username.show)作为道具传递然后尝试对其进行编辑时,它会给我一个avoid manipulating prop 警告。但是,如果我将tooltips.username 对象作为一个整体传递(比如v-bind:tooltip,然后使用`<... v-on:click="tooltip.show = false">,那么它可以正常工作而不会出现任何错误(并更改 Vue 实例中的原始 show 变量)。我猜这仍然是不好的做法,但是您是否碰巧知道为什么这样做有效,而前者却没有。
  • 我不完全确定,这可能与 Vue 的可观察对象的工作方式有关,它们可能没有附加到对象中的每个属性。如果组件被重新渲染,那么我想修改后的对象将被父级的未修改版本替换。其他东西可能会提供更多细节,但我绝对会避免这样做。
  • 复制您在 jsfiddle 中发布的方法时,它工作正常,但是在浏览器中使用它时,单击工具提示会隐藏它,但似乎也会暂时隐藏另一个工具提示(大约半秒- 之后它重新出现),在那之后,进一步的工具提示点击将不会做任何事情(在用户名或密码工具提示上)。这可能与自定义 @tooltip:hide 事件有关吗?
  • 在 Chrome 和 Safari 中测试。我加载了你的,它工作得很好,所以我必须检查我的代码,看看我哪里出错了。谢谢您的帮助! :)
  • 如果有人遇到与上述相同的问题,我意识到我在另一个 Vue 应用程序中有另一个组件,它在早期的测试中被称为 tooltip。将工具提示组件(它们几乎相同)移动/合并到一个单独的 javascript 文件中的一个全局组件中解决了问题并允许在两个单独的应用程序中使用工具提示
猜你喜欢
  • 1970-01-01
  • 2018-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-07
  • 2012-11-02
  • 1970-01-01
  • 2017-09-10
相关资源
最近更新 更多