vue性能问题

通过三个长度都为1000的数组循渲染原生input,自己封装的input,el-input

  1. 当注释掉el-input后,输入十分流畅
  2. 不注释掉el-input,输入十分卡顿,看了下vue-devtools,更新input,my-inputh,el-input都会导致所有的el-input同时更新,el-input的数量越多输入卡顿时间就越长

想知道为什么input,my-input,el-input都会引发el-input更新

附上我的测试代码

<template>
  <div>
    <div style="width: 100%; background-color: #ff0;">
      <input type="text" v-for="(item, index) in list1" v-model="item.value" :key="index" />
    </div>
    <div style="width: 100%; background-color: #f00;">
      <MyInput type="text" v-for="(item, index) in list2" v-model="item.value" :key="index + 'my'" />
    </div>
    <div style="width: 100%; background-color: #00f;">
      <el-input type="text" v-for="(item, index) in list3" v-model="item.value" :key="index + 'el'" />
    </div>
  </div>
</template>

<script>
import MyInput from "./myInput";

const length = 1000;

export default {
  name: "test",
  components: {
    MyInput,
  },
  data() {
    return {
      list1: Array(length)
        .fill(0)
        .map((_) => ({ value: "" })),
      list2: Array(length)
        .fill(0)
        .map((_) => ({ value: "" })),
      list3: Array(length)
        .fill(0)
        .map((_) => ({ value: "" })),
    };
  },
};
</script>

<style scoped></style>
<template>
  <div>
    <div>
      <div>
        <div>
          <input type="text" v-model="value" @input="handleInput" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "MyInput",
  props: {
    value: {
      type: String,
      default: "",
    },
  },
  methods: {
    handleInput(e) {
      this.$emit("input", e.target.value);
    },
  },
};
</script>

<style scoped></style>
阅读 3.3k
3 个回答

那就看源码呗

el-input 输入会有以下逻辑

// watch
value(val) {
    this.$nextTick(this.resizeTextarea);
    if (this.validateEvent) { // default true
      this.dispatch('ElFormItem', 'el.form.change', [val]);
    }
},

然后 resizeTextarea, 这里主要处理 type = textarea 情况可以忽略

// method
resizeTextarea() {
    if (this.$isServer) return;
    const { autosize, type } = this;
    if (type !== 'textarea') return;
    if (!autosize) {
      this.textareaCalcStyle = {
        minHeight: calcTextareaHeight(this.$refs.textarea).minHeight
      };
      return;
    }
    const minRows = autosize.minRows;
    const maxRows = autosize.maxRows;

    this.textareaCalcStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
}

需要注意的是 this.dispatch, 这是个通过 mixin 导入的方法,主要功能是触发上级目标父组件中的方法

dispatch(componentName, eventName, params) {
  var parent = this.$parent || this.$root;
  var name = parent.$options.componentName;
  // 递归寻找组件名匹配的父级组件
  while (parent && (!name || name !== componentName)) {
    parent = parent.$parent;
    if (parent) {
      name = parent.$options.componentName;
    }
  }
  // 如果找到了!
  if (parent) {
    // 目的达成
    parent.$emit.apply(parent, [eventName].concat(params));
  }
},

懒得往下撸了,我想表达的是你自己简单封装的组件考虑的情况比较少
而 element 考虑的情况会多一点
性能这种东西自己取舍呗

封装的 input 的 DOM 元素嵌套更多, 更改后渲染的成本也越大,我猜测是 DOM 过多导致的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题