vue2:
1.在调用组件父组件内 创建响应式数据 并使用v-model绑定传入封装好的input组件内
<template>
<div>
<el-form :rules="rules" ref="Form" :model="Form">
<el-form-item label="姓名" prop="name">
<Input v-model="Form.name" />
</el-form-item>
<el-form-item label="密码" prop="pwd">
<Input v-model="Form.pwd" />
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="submitForm"
style="marginLeft:110px ;"
>登录</el-button
>
</el-form-item>
</el-form>
</div>
</template>
<script>
import ElForm from "./ElForm.vue";
import ElFormItem from "./ElFormItem.vue";
import Input from "./Input.vue";
export default {
components: {
ElForm,
ElFormItem,
Input
},
data() {
return {
Form: { name: "11", pwd: "22" },
},
};
</script>
<style lang="scss" scoped>
</style>
2.input组件内使用value接收并绑定v-model传入值,在输入动作发生时,通过input事件,以及this.$emit将输入值赋值给v-model绑定的变量,注意 vue2 emit事件名必须是input
<template>
<div class="myInput">
<input type="text" @input="input" class="inputinner" :value="value" />
</div>
</template>
<script>
export default {
name: "MyInput",
props: {
value: {
type: String
}
},
data() {
return {};
},
methods: {
input(e) {
this.$emit("input", e.target.value);
}
}
};
</script>
<style lang="scss" scoped>
.myInput {
margin: 5px 10px;
.inputinner {
background-color: #fff;
background-image: none;
border-radius: 4px;
border: 1px solid #dcdfe6;
box-sizing: border-box;
color: #606266;
display: inline-block;
font-size: inherit;
height: 40px;
line-height: 40px;
outline: none;
padding: 0 15px;
transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
width: 100%;
}
}
</style>
vue3:
1.在调用组件父组件内 创建响应式数据 并使用v-model绑定传入封装好的input组件内
<template>
<div class="container">
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">邮箱地址</label>
<ValidateInput :rules="emailRules" **v-model="emailVal"** />
{{emailVal}}
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import 'bootstrap/dist/css/bootstrap.min.css'
import ValidateInput, { RulesProp } from './components/ValidateInput.vue'
export default defineComponent({
name: 'App*',*
components: {
ValidateInput
},
setup () {
** const emailVal = ref('你好')**
return {
emailVal
}
}
})
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin-top: 60px;
}
</style>
2.在子组件内props内 使用 modelValue 接收参数,并创建响应式数据 将modelValue初始化给该数据,并在input上使用:value绑定,当输入事件发生时,使用@input绑定事件,将回调参数赋值给响应式数据,并使用 context,emit('update:modelValue',e.target.value)实现双向绑定
<template>
<div class="validate-input-container pb-3 ">
<input type="text"
class="form-control"
:class="{'is-invalid': inputRef.error}"
** :value='inputRef.val'**
@blur="validateInput"
@input="updateValue"
>
<span v-if="inputRef.error" class="invalid-feedback">{{inputRef.message}}</span>
</div>
</template>
<script lang='ts'>
import { defineComponent, PropType, reactive } from 'vue'
const emailReg = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
interface RuleProp{
type:'required' | 'email';
message:string
}
export type RulesProp=RuleProp []
export default defineComponent({
props: {
rules: Array as PropType<RulesProp>,
** modelValue: {
type: String,
required: true
}**
},
setup (props, context) {
const inputRef = reactive({
** val: props.modelValue,**
error: false,
message: ''
})
** const updateValue = (e:KeyboardEvent) => {
const targetValue = (e.target as HTMLInputElement).value
inputRef.val = targetValue
context.emit('update:modelValue', targetValue)
}**
const validateInput = () => {
if (props.rules) {
const allPassed = props.rules.every(rule => {
let passed = true
inputRef.message = rule.message
switch (rule.type) {
case 'required':
passed = (inputRef.val.trim() !== '')
break
case 'email':
passed = emailReg.test(inputRef.val)
break
default:
break
}
return passed
})
inputRef.error = !allPassed
}
}
return {
validateInput,
inputRef,
updateValue
}
}
})
</script>
<style lang="scss" scoped>
</style>