Javascript 从组件内部更改vue实例变量

Javascript 从组件内部更改vue实例变量,javascript,vue.js,vue-component,Javascript,Vue.js,Vue Component,我一直在自学Vue.js,并一直在利用组件来提高模块化程度 我正在努力解决的一件事是从组件内部操纵Vue实例中的变量。通过将jade文件中的变量作为prop传递,我已经使它能够在组件中与v-model很好地工作 例如loginform(slot=“login form”v-bind:form submit=“loginSubmit”v-bind:login data=“loginnada”) 其中loginData包含变量username和password,这些变量是组件内输入的'v-model

我一直在自学Vue.js,并一直在利用组件来提高模块化程度

我正在努力解决的一件事是从组件内部操纵Vue实例中的变量。通过将jade文件中的变量作为prop传递,我已经使它能够在组件中与
v-model
很好地工作

例如
loginform(slot=“login form”v-bind:form submit=“loginSubmit”v-bind:login data=“loginnada”)

其中loginData包含变量username和password,这些变量是组件内输入的
'v-modeled'
。然后在组件模板中:

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

我似乎无法将该变量作为道具传递,以便在未获得
避免操作道具
警告的情况下进行操作,尽管组件中的
v-model
未给出这些警告。工具提示组件如下所示:

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>
}); 
Vue.component('tooltip'{
道具:['show','message','click'],
模板:
{{message}}
}); 

有人知道我怎样才能达到想要的效果吗(鼠标点击时隐藏工具提示)。我尝试将一个方法作为click prop传递,该方法根据工具提示是用于用户名还是密码输入而具有不同的参数,但是我收到了click undefined警告。我可以创建两个独立的函数,但我不希望显式地编写两个做相同事情的函数。

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

对于您想要实现的目标,您应该查看Vue的自定义事件

HTML


用户名
密码
JS

Vue.component('tooltip'{
道具:['show','message'],
模板:`
{{message}}
`,
方法:{
隐藏(){
此.emit('tooltip:hide');
},
}
}); 
新Vue({
el:“应用程序”,
数据:{
表格数据:{
用户名:“”,
密码:“”
},
工具提示:{
用户名:{
消息:“修复您的用户名”,
维斯:是的
},
密码:{
消息:“修复您的密码”,
维斯:是的
}
}
}
});

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

对于您想要实现的目标,您应该查看Vue的自定义事件

HTML


用户名
密码
JS

Vue.component('tooltip'{
道具:['show','message'],
模板:`
{{message}}
`,
方法:{
隐藏(){
此.emit('tooltip:hide');
},
}
}); 
新Vue({
el:“应用程序”,
数据:{
表格数据:{
用户名:“”,
密码:“”
},
工具提示:{
用户名:{
消息:“修复您的用户名”,
维斯:是的
},
密码:{
消息:“修复您的密码”,
维斯:是的
}
}
}
});

您的用户名/密码
v-model
不会发出警告,因为您正在为道具传递一个对象,然后更新该对象中的属性。道具仍在引用同一对象。如果你在没有包装器的情况下通过它们,你会看到同样的警告。@skille啊,谢谢!你刚才回答了我对以下答案的评论。感谢您澄清:)您的用户名/密码
v-model
不会发出警告,因为您正在为道具传递一个对象,然后更新该对象中的属性。道具仍在引用同一对象。如果你在没有包装器的情况下通过它们,你会看到同样的警告。@skille啊,谢谢!你刚才回答了我对以下答案的评论。谢谢你的澄清:)哦,谢谢你完美地回答了这个问题。我只是事先注意到,当我将可见性变量(
tooltips.username.show
)直接作为道具传递,然后尝试编辑它时,它会给我一个
避免操纵道具的警告。但是,如果我将
tooltips.username
对象作为一个整体传递(例如作为
v-bind:tooltipp
,然后使用“”,则它可以正常工作,不会出现任何错误(并更改Vue实例中的原始show变量)。我猜这仍然是一种不好的做法,但您是否知道为什么这样做有效,而前者不行。我不完全确定,这可能与Vue的可观察对象的工作方式有关,它们可能没有连接到对象中的每个属性。如果重新渲染组件,则我认为修改后的对象将被来自父级的未修改版本。其他一些东西可能能够提供更多详细信息,但我肯定不会这样做。当复制您在JSFIDLE中发布的方法时,它工作正常,但在浏览器中使用时,单击工具提示将隐藏它,但似乎也会暂时隐藏其他工具提示(大约半秒钟-之后它会重新出现),在那之后,进一步的工具提示单击将不会做任何事情(在用户名或密码工具提示上)。这可能是在Chrome和Safari中测试的自定义@tooltip:hide事件中的某件事吗?我加载了你的一个,效果很好,所以我必须通过
<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>
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
        }
    }
    }
});