Инкапсуляция компонентов Vue v-model (аналогично компонентам всплывающих окон)

Vue.js

v-model

v-model — это синтаксический сахар для Vue, который ограничен элементами формы, такими как input и textarea Примеры, приведенные на официальном сайте, также ограничены компонентами формы.

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})
<base-checkbox v-model="lovingVue"></base-checkbox>

Теперь, если мы хотим использовать v-model в пользовательских компонентах, отличных от форм, как мы должны его использовать?На самом деле примеры, приведенные на официальном сайте, относительно ясны, но если мы тугодумы, это будет ограничено, да Я говорю о -.-.

<!--封装的类弹窗组件-->
<template>
    <div>
        <div v-show="value">这是v-model的弹窗组件</div>
    </div>
</template>
<script>
export default {
    props:{
        value:{
            type:Boolean,
            default:false
        }
    }
}
</script>
<!--父组件-->
<template>
    <div>
        <v-model v-model="value"></v-model>
        <button @click="value=true">点击显示</button>
        <button @click="value=false">点击消失</button>
    </div>
</template>
<script>
import VModel from "./Vmodel"
export default {
    components:{VModel},
    data:function(){
        return {
            value:true
        }
    }
}
</script>

На самом деле родительский компонент уже может управлять отображением и исчезновением через v-model, а вот компонент инкапсуляцииvalueЭто имя свойства не может быть изменено и должно вызыватьсяvalue,Вызовvalue1не могу

props:{
        value1:{  //失效
            type:Boolean,
            default:false
        }
    }

Причина, см. исходный код

function transformModel (options, data: any) {
  const prop = (options.model && options.model.prop) || 'value' //子组件不存在options.model,默认给value
  const event = (options.model && options.model.event) || 'input'//event="input"
  ;(data.attrs || (data.attrs = {}))[prop] = data.model.value
  const on = data.on || (data.on = {})
  const existing = on[event]  //undefined
  const callback = data.model.callback  //f()
  if (isDef(existing)) {  //false
    if (
      Array.isArray(existing)
        ? existing.indexOf(callback) === -1
        : existing !== callback
    ) {
      on[event] = [callback].concat(existing)
    }
  } else {
    on[event] = callback  //把回调赋值给监听的函数
  }
}

Итак, мы можем добавить атрибут модели для изменения кода.

<template>
    <div>
        <div v-show="value">这是v-model的弹窗组件</div>
        <div @click="cancelClick">组件内部调用</div>
    </div>
</template>
<script>
export default {
    props:{
        value:{
            type:Boolean,
            default:false
        }
    },
    model:{
        prop:"value",
        event:'change'
    },
    methods:{
        cancelClick:function(){
            //内部调用这个方法可以进行控制
            this.$emit("change",false)
        }
    }
}
</script>

Конечно, мы также можем изменить имя атрибута значения через атрибут модели, что также дает тот же эффект.

bool:{
        type:Boolean,
        default:false
    },
model:{
    prop:"bool",
    event:'change'
}

Обратите внимание, что если атрибут модели добавлен, это не повлияет на изменение имени атрибута значения реквизита.По умолчанию событие v-model изменяется по значению.

 const prop = (options.model && options.model.prop) || 'value' //子组件不存在options.model,默认给value
  const event = (options.model && options.model.event) || 'input'//event="input"