除非我刷新页面,否则 Vue data() 对象输入 v-model 不起作用
Posted
技术标签:
【中文标题】除非我刷新页面,否则 Vue data() 对象输入 v-model 不起作用【英文标题】:Vue data() object Input v-model doesn't work unless I refresh the page 【发布时间】:2021-06-17 05:32:15 【问题描述】:所以这很难解释,相反我制作了一个视频来展示正在发生的事情:
https://www.youtube.com/watch?v=md0FWeRhVkE
分步说明:
用户可以创建一个新帐户。 此用户将自动登录(尚无电子邮件验证步骤)。 然后在不刷新页面的情况下,我尝试添加一个类别。 有一个自定义组件被 v 建模为 data() 值(正如您在视频中看到的,这是 category_name。 每当我在输入字段中填写内容时,这应该会显示在输入字段的上方(因为我正在那里转储值)。您会发现在页面刷新之前不会发生这种情况。 但是当我刷新页面时,v-model 突然起作用了。有人知道我最初注册用户时发生了什么以及为什么它不起作用吗?除非您刷新页面,否则似乎不会创建 data() 值 category_name
或其他东西?
谢谢!
【问题讨论】:
您是否可以分享您在视频中显示的文件,以便我们自己尝试重现问题? 当然这里是 repo:github.com/Danielvandervelden/snippets 填写 env 文件。在客户端运行 npm run serve 并在服务器中运行 npm start 。确保在 mysql 中创建数据库。 您是否尝试在data()
中将初始非空值设置为category_name
?喜欢category_name: ''
@Daniel - 我无法重现您描述的问题......它似乎对我来说很好。
【参考方案1】:
您的自定义输入 (Input.vue
) 未声明和使用 v-model
绑定的 value
属性 - 请参阅 v-model
on custom component works 上的文档
这不是只有双向绑定才需要吗?如我所见,绑定 value 属性只允许从父级更改输入值
嗯,不完全是。 value
绑定(“来自父级的值”)在任何时候创建和重用组件时都是必不可少的。
重用现有组件实例是 Vue 使用的非常常见(且有用)的优化策略。您可以使用下面的示例来查看缺少 value
竞价对自定义输入的影响。
组件的创建频率超出您的想象。切换到“Fixed”组件并返回演示了在动态创建组件的情况下(例如,在路由器视图或某种自定义“Tab”组件中使用时),v-model
没有绑定value
是如何损坏的
我知道这是“远射”——我不确定这是否能解决问题(共享 git repo 不符合我对 Minimal, Reproducible Example 的定义)但是这绝对是一个错误而且我没有看到其他代码有什么特别错误的地方......
考虑到没有value
的自定义输入是多么糟糕,有理由认为 Vue 开发人员从未预料到这样的用法,并且它可能导致各种“奇怪”和意想不到的行为......
Vue.component('my-input-broken',
props: ['name', 'type', 'label'],
methods:
inputHandler(e)
this.$emit('input', e.target.value);
,
,
template: `
<div v-if="name && type" :id="name">
<input v-if="type !== 'textarea'" @input="inputHandler" :name="name" :type="type" />
<textarea v-else-if="type === 'textarea'" @input="inputHandler" @blur="blurHandler($event)" :name="name" type="textarea" />
<label v-if="label" :for="name">label</label>
</div>
`
)
Vue.component('my-input-fixed',
props: ['name', 'type', 'label', 'value'],
methods:
inputHandler(e)
this.$emit('input', e.target.value);
,
,
template: `
<div v-if="name && type" :id="name">
<input v-if="type !== 'textarea'" @input="inputHandler" :name="name" :type="type" :value='value' />
<textarea v-else-if="type === 'textarea'" @input="inputHandler" @blur="blurHandler($event)" :name="name" :value='value' type="textarea" />
<label v-if="label" :for="name">label</label>
</div>
`
)
const vm = new Vue(
el: '#app',
data: function()
return
values: [""],
componentToUse: 'a'
,
methods:
addInput()
this.values.unshift("")
,
computed:
comp()
return this.componentToUse === 'a' ? "my-input-broken" : "my-input-fixed"
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<div id="app">
<label for="componentToUse">Component to use:</label>
<input type="radio" name="componentToUse" v-model="componentToUse" value="a"> Broken
<input type="radio" name="componentToUse" v-model="componentToUse" value="b"> Fixed
<hr>
<button @click="addInput">Add at beginning...</button>
<component :is="comp" v-for="(value, index) in values" :key="index" v-model="values[index]" :name="`value_$index`" type="text" :label="`value_$index ('$values[index]')`"></component>
</div>
【讨论】:
那不是只有双向绑定才需要吗?正如我所看到的,绑定 value 属性只允许从父级更改输入值,但是将数据从子组件传递给父级似乎没有什么区别,这是由$emit
处理的, 除非这只是 v-model
正常运行所必需的。
你赢了。谢谢!从来不知道我实际上也必须绑定值,因为我认为 v-model 会这样做。
@Daniel 是的,v-model
绑定到您的自定义组件的 value
属性中。但要使其工作,您需要将value
属性在组件内绑定到本机<input>
元素的value
属性。再次检查我链接的文档和我的示例。您的最后一次提交没有解决问题....【参考方案2】:
我想我现在明白v-model
的主要问题了。
<input v-model="myObject[attribute]" />
等价于
<input
v-bind:value="myObject[attribute]"
v-on:input="myObject[attribute] = $event"
/>
在我的情况下,问题是在重新分配 myObject[attribute]
后 GUI 没有刷新。
我对这个问题的解决方法是在重新分配变量后调用$forceUpdate()
,如下所示:
<input
v-bind:value="myObject[attribute]"
v-on:input="myObject[attribute] = $event; $forceUpdate()"
/>
不确定这是否能解决您的问题,但我希望它可以帮助遇到同样问题的人。
【讨论】:
以上是关于除非我刷新页面,否则 Vue data() 对象输入 v-model 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
除非我刷新,否则 jQuery mobile 中的 JavaScript 不起作用
SmartEdit:除非刷新页面,否则嵌套 CMS 组件中的更改不会反映
除非刷新页面,否则React loadable无法在每个新构建上加载组件