美文网首页
vue3中自定义组件v-model的实现

vue3中自定义组件v-model的实现

作者: 泡杯感冒灵 | 来源:发表于2021-08-11 21:57 被阅读0次

    主要的两个步骤

    1. 自定义组件创建 props属性 modelValue
    2. 自定义组件触发update:modelValue事件,并把值传出去
    <template>
        <div class="validate-input-container pb-3">
            <input
                class="form-control"
                :class="{'is-invalid':inputRef.error}"
                :value="inputRef.val"
                @blur="validateEmail"
                @input="updateValue"
            >
            <div class="invalid-feedback" v-if="inputRef.error">
                {{inputRef.message}}
            </div>
        </div>
    </template>
    
    <script lang="ts">
    import { defineComponent, reactive, PropType } from 'vue'
    const emailReg = /^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$/
    interface RuleProp {
        type: 'required' | 'email'
        message: string
    }
    export type RulesProp = RuleProp[]
    export default defineComponent({
      name: 'ValidateInput',
      props: {
        rules: Array as PropType<RulesProp>,
        modelValue: String
      },
      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 validateEmail = () => {
          if (props.rules) {
            // 因为需要每个规则都通过才可以,所以用数组的every方法
            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.trim())
                  break
                default:
                  break
              }
              return passed
            })
            inputRef.error = !allPassed
          }
        }
        return {
          inputRef,
          validateEmail,
          updateValue
        }
      }
    })
    </script>
    
    
    然后就是调用组件的地方 v-model就可以使用了
    <template>
      <div class="container">
        <global-header :user="currentUser"></global-header>
        <form>
          <div class="mb-3">
            <label for="exampleInputEmail1" class="form-label">邮箱地址</label>
            <validate-input :rules="emailRules" v-model="emailVal"></validate-input>
            {{emailVal}}
          </div>
        </form>
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent, reactive, ref } from 'vue'
    import 'bootstrap/dist/css/bootstrap.min.css'
    import GlobalHeader, { UserProps } from './components/GlobalHeader.vue'
    import ValidateInput, { RulesProp } from './components/ValidateInput.vue'
    const currentUser:UserProps = {
      isLogin: true,
      name: 'weiyang'
    }
    
    export default defineComponent({
      name: 'App',
      components: {
        GlobalHeader,
        ValidateInput
      },
      setup () {
        const emailVal = ref('weiyang')
        const emailRules: RulesProp = [
          { type: 'required', message: '电子邮箱地址不能为空' },
          { type: 'email', message: '请输入正确的电子邮箱格式' }
        ]
        return {
          currentUser,
          emailRules,
          emailVal
        }
      }
    
    })
    </script>
    
    <style>
    </style>
    
    

    相关文章

      网友评论

          本文标题:vue3中自定义组件v-model的实现

          本文链接:https://www.haomeiwen.com/subject/uhwhbltx.html