这篇“vue2怎么封装input组件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue2怎么封装input组件”文章吧。
vue2封装input组件
重点
首先我们要明白 vue中v-modle 的对于input 做了什么
<input type="text" v-model="username"> <input type="text" :value="username" @input="username = $event.target.value">
以上的两行代码,所呈现的效果是一样的。也就是说: v-model=“username” 在input中做了两件事情。
:value 绑定了值
@input=“username = $event.target.value” 监听了值的改变
代码示例:
父组件
<template> <div id="app"> <lj-input placeholder="请输入" v-model="username"></lj-input> <div>{{username}}</div> </div> </template> <script> import ljInput from './components/inputCom/LjInput.vue' export default { name: 'App', components: { ljInput }, data(){ return{ username:'', } }, methods: { } } </script>
子组件
<template> <div class="lj-input"> <input :class="{'is-disabled':disabled}" :placeholder="placeholder" :type="type" :disabled ='disabled' :value="value" @input="handleInput" > </div> </template> <script> export default { name:'ljInput', props: { placeholder:{ type:String, default:'' }, type:{ type:String, default:'' }, disabled:{ type:Boolean, default:false }, value:{ type:String, default:'' } }, methods:{ handleInput(e){ // 这句代码是关键 this.$emit('input',e.target.value) } } } </script> <style> .is-disabled{ cursor: not-allowed; } </style>
vue二次封装input的几种方式
下面就是自己封装input 框实现的效果
在看如何封装之前,先来了解一下v-model是怎么回事。
其实说白了,v-model就是change和value的结合体。
废话不多说,下面就来看一下在vue中如何封装自定义的input组件。
封装原生input
<template> <input type="text" :value="value" @input="handleChange" /> </template> <script> export default { name: "AppInput", model: { prop: "value", event: "change", }, props: { value: "", }, data() { return { }; }, created() {}, mounted() {}, methods: { handleChange(e) { this.$emit("change", e.target.value); }, }, }; </script>
封装el-input
<template> <!-- 对el-input进行了包装--> <div> <el-input v-model="localValue" @change="$emit('change', $event)"></el-input> <!-- el-input提供了input事件,让我们感知el-input内部原生input值的变化,通过$event可以获取到具体的值 通过emit再次传递给父组件一个input事件,父组件中,v-on:input="searchText = $event"这句就能正常使用了 --> <span ></span> </div> </template> <script> export default { name: "input-name", props: { // 保证父组件中,v-bind:value可以正常设置值 value: [String], }, data() { return { // 获取props中value的值,并与el-input绑定,过程中不修改props中value的值,保证了单向数据流原则 localValue: this.value } } } </script> <style lang="less" scoped> </style>
上面的那种方式会在回显数据时有问题。解决办法就是:如果出现异步回显数据那么就需要用计算来作为中间值转换。
<template> <!-- 对el-input进行了包装--> <div> <el-input v-model="localValue" @change="$emit('change', $event)"></el-input> <!-- el-input提供了input事件,让我们感知el-input内部原生input值的变化,通过$event可以获取到具体的值 通过emit再次传递给父组件一个input事件,父组件中,v-on:input="searchText = $event"这句就能正常使用了 --> <span ></span> </div> </template> <script> export default { name: "input-name", props: { // 保证父组件中,v-bind:value可以正常设置值 value: [String], }, data() { return { } }, computed: { localValue: { get: function () { console.log(this.value) return this.value; }, set: function (v) { v; }, }, }, } </script> <style lang="less" scoped> </style>
VUE高级用法封装input
这种方式更加简洁,并且不会出现第二种封装方式出现的bug。
<template> //这里不能使用v-model,会报子组件不能直接操作父组件传入参数的错误 //使用value的话其实就是做一个回显因为外层的v-model在这里使用已经改变了外层的值了 <el-input v-bind="$attrs" v-on="$listeners" :value="value" ></el-input> </template> <script> export default { name: "f-input", data() { return { }; }, props: { value:"" }, created() {}, mounted() {}, methods: {} }; </script>
//正常的使用方式 <f-input v-model="number"></f-input> //不用v-model语法糖的方式 <f-input :value="number" @change="number = $event,target.value"></f-input>
这里核心用到了两个方法 attrs 和 listeners 其中 atters 可以把父组件标签上的所有自定义属性(不包括props,tyle,class)同步到当前元素中,listeners 可以把 f-input 标签上的所有方法同步到子组件中当前元素中。
那么上面已经知道 v-model 就是 change 和 value 的语法糖,那在 f-input 上绑定 listeners 就可以读取到 f-input 的 v-model 的 change 事件,atters 可以读取到 f-input 的 v-model 的 value 值。
$ 符号打不出来了,将就着看吧。如果还是不明白 atters和 listeners是怎么回事的可以看一下vue官网中的介绍。
看官网又出了一种封装的写法,感觉挺有意思,在这里记录一下。
默认情况下,组件上的 v-model 使用 modelValue 作为 prop 和 update:modelValue 作为事件。我们可以通过向 v-model 传递参数来修改这些名称
子组件将需要一个 firstName prop 和 lastName prop并发出 update:firstName 和 update:lastName要同步的事件
var Component = { props: { firstName: String, lastName: String }, emits: ['update:firstName', 'update:lastName'], //vue3可以支持多个根元素,所有这个地方不会有报错,vue2是会报错的。 template: ` <input type="text" :value="firstName" @input="$emit('update:firstName', $event.target.value)"> <input type="text" :value="lastName" @input="$emit('update:lastName', $event.target.value)"> ` }
<template> <my-component v-model:first-name="firstName" v-model:last-name="lastName"> </my-component> firstName:{{firstName}} lastName:{{lastName}} </template> <script> const App = { setup(props, context) { const data= reactive({ firstName: 0, lastName: 0, }); return { ...toRefs(data), } }, components: { 'my-component': Component, }, methods: { }, }; const app = createApp(App).mount('#app'); </script>