Vue自定义组件父组件blur事件绑定失效问题求助
嘿,我来帮你排查下这个问题~你的代码里有两个关键问题导致blur事件没触发,还有一个v-model的小问题需要修正,咱们一步步来:
为什么blur事件没触发?
你在父组件里给自定义的<text-input>绑定了v-on:blur="leave",但Vue的自定义组件默认不会把父组件绑定的原生DOM事件(比如blur)传递给内部的DOM元素。这个事件其实是绑定在<text-input>组件实例上,而不是内部的<input>标签上,所以当你离开输入框时,自然不会触发父组件的leave方法。
解决方案一:使用.native修饰符监听原生事件
如果你的自定义组件根元素就是<input>(就像现在的代码),可以直接给事件绑定加上.native修饰符,这样Vue会把事件绑定到组件的根DOM元素上:
修改后的HTML部分:
<div id='app'> <div class="form-group"> <text-input class="form-control" v-for="input in inputs" v-bind:args="input" v-bind:key="input.id" v-on:blur.native="leave" /> </div> </div>
解决方案二:组件内部显式传递事件(更推荐)
如果以后你的组件模板可能会修改(比如根元素不再是input),或者你想更符合组件封装的规范,建议在自定义组件内部给<input>绑定blur事件,然后通过$emit把事件传递给父组件:
修改后的组件代码:
Vue.component('text-input', { props: ['args'], template: '<input :id="args.id" :type="args.type" @blur="$emit(\'blur\', $event)"/>' })
这样父组件里原来的v-on:blur="leave"就可以正常工作了,不需要加.native。
额外修正:v-model的问题
你现在给<text-input>用了v-model="input.id",但自定义组件要支持v-model,需要满足两个条件:
- 接收一个
valueprop - 在输入变化时
$emit('input', 新值)
如果你需要v-model功能,可以修改组件如下:
Vue.component('text-input', { props: ['args', 'value'], template: '<input :id="args.id" :type="args.type" :value="value" @input="$emit(\'input\', $event.target.value)" @blur="$emit(\'blur\', $event)"/>' })
然后父组件的v-model就可以正确绑定数据了:
<text-input class="form-control" v-for="input in inputs" v-bind:args="input" v-bind:key="input.id" v-model="input.value" v-on:blur="leave" />
(注意这里把input.id改成了input.value,因为input.id是固定的标识,用来绑定输入值不合适,建议在data的inputs里加value字段)
最终完整代码示例(推荐方案)
Vue.component('text-input', { props: ['args', 'value'], template: '<input :id="args.id" :type="args.type" :value="value" @input="$emit(\'input\', $event.target.value)" @blur="$emit(\'blur\', $event)"/>' }) App = new Vue({ el : '#app', data: { inputs : [ { id : 'nickname', type : 'text', value: ''}, { id : 'email' , type:'email', value: ''}, ] }, methods : { leave : function(event) { var id = event.target.id; // 这里不需要jQuery,Vue的event.target就是DOM元素 console.log('left object ' + id); } } })
<div id='app'> <div class="form-group"> <text-input class="form-control" v-for="input in inputs" v-bind:args="input" v-bind:key="input.id" v-model="input.value" v-on:blur="leave" /> </div> </div>
另外,你的leave方法里用了jQuery,其实直接通过event.target.id就能获取到输入框的ID,不需要依赖jQuery哦~
内容的提问来源于stack exchange,提问作者yhc44

