模板变化

# 模板变化

v-model的变化

v-model修饰符

我们先来看 v-model 的变化,以前我们可以通过特定的方式定义组件来使用 v-model 简化代码,如果想要定义第二个 v-model 是无法实现的,只能通过属性定义修饰符(如::value.sync)来替代这个方式,但是啊 这两种方式虽然看上去不同,但是实现是一样的。所以 vue3 中作者就二选其一去掉了其中一个。

  • v-model 的变化

    v-model实质

    <ChileComp :value @input="value=$event" />
    

    简写为

    <ChileComp v-model:value />
    

    何为 v-model 就是定义一个 props 和 一个 事件 然后 通过事件修改 props值

    这是我们以前的做法

    然而 Vue3 觉得 两种方法有些重复就删掉了修饰符替代的那种

    大体上还是没变

    也是定义一个 props 和 一个事件 只不过 默认情况下,props 是 modelValue,然后我们要修改的是 modelValue 的值 所以事件为 update:modelValue.

    father

    <v-modal-test
        v-for="item in dateRef"
        :key="item.id"
        v-model="item.status"
      />
    

    child

    <template>
      <input type="checkbox" :checked="modelValue" @change="handleChange" />
    </template>
    <script>
    export default {
      props: {
        modelValue: Boolean,
        update: Function,
      },
    };
    </script>
    

    继续,

    我们通过定义的 handleChange 事件拿到 event.target.checked 这个 checkbox 的值后怎么来触发父组件的事件呢? 以前是通过 this.$emit 但是现在没有 this 了

    setup 存在两个参数

    params1:props 这个属性指向的是我们的 props

    Params2:这个属性是一些组件内置函数 这里面有emit、slots、attrs

    这样可以继续进行了,

      setup(props, self) {
        const handleChange = (e) => {
          self.emit("update:modelValue", e.target.checked);
        };
    
        return {
          handleChange,
        };
      },
    

    那么我们如何定义第二个 v-model 呢?

    可以通过给 v-model 添加属性的方式 如 v-model:text , 然后子组件 通过 update 事件修改 text 的属性值 就 ok 了 update:text

    father

    <v-modal-test
        v-for="item in dateRef"
        :key="item.id"
        v-model="item.status"
        v-model:text="item.name"
      />
    

    child

    <template>
      <input type="checkbox" :checked="modelValue" @change="handleChange" />
      <input type="text" :value="text" @input="handleInput" />
    </template>
    <script>
    export default {
      props: {
        modelValue: Boolean,
        update: Function,
        text: String,
      },
      setup(props, self) {
        const handleChange = (e) => {
          self.emit("update:modelValue", e.target.checked);
        };
    
        const handleInput = (e) => {
          let val = e.target.value;
          self.emit("update:text", val);
        };
    
        return {
          handleChange,
          handleInput,
        };
      },
    };
    </script>
    
  • 修饰符

    Vue3 删除了修饰符功能,改为自定义的方式。

    怎么自定义呢?

    父组件呢还是和原来保持不变,只不过逻辑全都交由子组件实现。

    father

    <v-modal-test
        v-for="item in dateRef"
        :key="item.id"
        v-model="item.status"
        v-model:text.trim="item.name"
      />
    

    我们在 text 属性那里添加了修饰符 trim 在 Vue2 中已经内置不需处理,但 Vue3 不同

    我们要在子组件的 props 中定义一个 Modifiers 如果你定义了修饰符,会自定帮你放入Modifiers 中。 定义方式是 属性名 + Modifiers

    Child

    props: {
        modelValue: Boolean,
        update: Function,
        text: String,
        textModifiers: {
          default: () => ({}),
        },
      },
    

    观察结果:我们定义了 trim 修饰符,然后 它就帮我们把 trim 这个属性放入了 textModifiers 很灵活

    textModifiers:{
    	trim: true
    }
    

    接下来我们只需要在使用的时候按需使用就可以了

        const handleInput = (e) => {
          let val = e.target.value;
          if (props.textModifiers.trim) {
            val = val.trim();
          }
          self.emit("update:text", val);
        };
    

    完整代码:Child

    <template>
      <input type="checkbox" :checked="modelValue" @change="handleChange" />
      <input type="text" :value="text" @input="handleInput" />
    </template>
    <script>
    export default {
      props: {
        modelValue: Boolean,
        update: Function,
        text: String,
        textModifiers: {
          default: () => ({}),
        },
      },
      setup(props, self) {
        const handleChange = (e) => {
          self.emit("update:modelValue", e.target.checked);
        };
    
        const handleInput = (e) => {
          let val = e.target.value;
          if (props.textModifiers.trim) {
            val = val.trim();
          }
          self.emit("update:text", val);
        };
    
        return {
          handleChange,
          handleInput,
        };
      },
    };
    </script>