封装input组件的时候 - 双向同步、加去空格、加防抖

600 阅读1分钟

当我们自己封装表单组件的时候,要留意双向同步的问题,而输入框的话,还需要留意空格防抖的小事项。

先来个最简单的 input 组件 InputStrong,此时均没有上面的三项:

<template>
  <input type="text" v-model="inputValue" />
</template>

<script lang="ts" setup>
import { ref, defineProps, watch, defineEmits } from 'vue';

// modelValue 是父组件传递过来的值
const props = defineProps<{ modelValue: string }>();

// inputValue 是当前组件的值
const inputValue = ref(props.modelValue);
</script>

使用的时候:

// <input-strong v-model="value" />
// <div>{{value}}</div>
// <button @click=" () => { value = '3' } " > 变成3 </button>
const value = ref('初始值');

input2 input1

双向同步

表单组件,同步非常重要,而且是双向的:

  • 子组件内部的值发生变化的时候,需要将父组件的值也同步
  • 父组件值发生变化的时候,需要将子组件的值也同步
<script lang="ts" setup>
import { ref, defineProps, watch, defineEmits } from 'vue';

// modelValue 是父组件传递过来的值
const props = defineProps<{ modelValue: string }>();
// update:modelValue 是父组件监听的事件
const emit = defineEmits(['update:modelValue']);

// inputValue 是当前组件的值
const inputValue = ref(props.modelValue);

// 监听当前组件的值变化,同步给父组件
watch(inputValue, (innerValue) => {
  emit('update:modelValue', innerValue);
});

// 监听父组件的值变化,同步给当前组件
watch(
  () => props.modelValue,
  (outerValue) => {
    inputValue.value = outerValue;
  }
);
</script>

input3

去前后空格

大部分场景下,前后的空格并不需要,所以可以在组件内部就处理好

// 监听当前组件的值变化,同步给父组件
watch(inputValue, (innerValue) => {
  emit('update:modelValue', innerValue.trim());
});

加防抖

输入的时候,触发变化是很快的,但很多时候并不需要那么快,所以加个防抖debounce即可。
debounce是 在事件被触发n秒后,再去执行回调函数。如果n秒内该事件被重新触发,则重新计时。结果就是将频繁触发的事件合并为一次,且在最后执行。

生活场景:电梯5秒后会关门开始运作,如果有人进来,等待5秒,5秒之内又有人进来,5秒等待重新计时...直至超过5秒,电梯才开始运作。

使用场景:input输入数据时请求服务器等。特别适合这里

这边使用一个小巧的库throttle-debounce

// import { debounce } from "throttle-debounce";
watch(
  inputValue,
  debounce(200, (innerValue: string) => {
    emit("update:modelValue", innerValue.trim());
  })
);

最终版input-strong

<template>
  <input type="text" v-model="inputValue" />
</template>

<script lang="ts" setup>
import { ref, defineProps, watch, defineEmits } from "vue";
import { debounce } from "throttle-debounce";

// modelValue 是父组件传递过来的值
const props = defineProps<{ modelValue: string }>();
// update:modelValue 是父组件监听的事件
const emit = defineEmits(["update:modelValue"]);

// inputValue 是当前组件的值
const inputValue = ref(props.modelValue);

// 监听当前组件的值变化,同步给父组件
watch(
  inputValue,
  debounce(200, (innerValue: string) => {
    emit("update:modelValue", innerValue.trim());
  })
);

// 监听父组件的值变化,同步给当前组件
watch(
  () => props.modelValue,
  (outerValue: string) => {
    inputValue.value = outerValue;
  }
);
</script>