Heim  >  Artikel  >  Web-Frontend  >  9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung

9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung

青灯夜游
青灯夜游nach vorne
2022-06-07 11:55:442533Durchsuche

In diesem Artikel werde ich einige Tipps mit Ihnen teilen, die ich während meines Studiums von Vue gelernt habe, um die Entwicklungseffizienz und -leistung zu verbessern. Ich hoffe, dass er für alle hilfreich sein wird!

9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung

1. Verwenden Sie $attrs und $listeners

geschickt zum Aufzeichnen aller von der übergeordneten Komponente an die untergeordnete Komponente übergebenen Parameter werden nicht von props erfasst und sind nicht class und style, und $listeners code> wird zum Aufzeichnen aller verwendet Ereignisse, die von der übergeordneten Komponente ohne den Dekorator .native übergeben werden. (Teilen von Lernvideos: vuejs Video-Tutorial$attrs$listeners

$attrs用于记录从父组件传入子组件的所有不被props捕获以及不是classstyle的参数,而$listeners用于记录从父组件传入的所有不含.native修饰器的事件。(学习视频分享:vuejs视频教程

那下面的代码作例子:

Vue.component('child', {
  props: ['title'],
  template: &#39;<h3>{{ title }}</h3>&#39;
})

new Vue({
  data:{a:1,title:&#39;title&#39;},
  methods:{
    handleClick(){
      // ...
    },
    handleChange(){
      // ...
    }
  },
  template:&#39;
    <child class="child-width" :a="a" b="1" :title="title" @click.native="handleClick" @change="handleChange">&#39;,

})

则在<child></child>在中

  • attrs的值为{a:1,b:"1"}
  • listeners的值为{change: handleChange}

通常我们可以用$attrs$listeners作组件通信,在二次封装组件中使用时比较高效,如:

Vue.component("custom-dialog", {
  // 通过v-bind="$attrs"和v-on="$listeners"把父组件传入的参数和事件都注入到el-dialog实例上
  template: '<el-dialog></el-dialog>',
});

new Vue({
  data: { visible: false },
  // 这样子就可以像在el-dialog一样用visible控制custom-dialog的显示和消失
  template: '<custom-dialog>',
});</custom-dialog>

再举个例子:

Vue.component("custom-select", {
  template: `<el-select v-bind="$attrs" v-on="$listeners">
    <el-option value="选项1" label="黄金糕"/>
    <el-option value="选项2" label="双皮奶"/>
  </el-select>`,
});

new Vue({
  data: { value: "" },
  // v-model在这里其实是v-bind:value和v-on:change的组合,
  // 在custom-select里,通过v-bind="$attrs" v-on="$listeners"的注入,
  // 把父组件上的value值双向绑定到custom-select组件里的el-select上,相当于<el-select v-model="value">
  // 与此同时,在custom-select注入的size变量也会通过v-bind="$attrs"注入到el-select上,从而控制el-select的大小
  template: &#39;<custom-select v-model="value" size="small">&#39;,
});

2. 巧用$props

$porps用于记录从父组件传入子组件的所有被props捕获以及不是classstyle的参数。如

Vue.component(&#39;child&#39;, {
  props: [&#39;title&#39;],
  template: &#39;<h3>{{ title }}</h3>&#39;
})

new Vue({
  data:{a:1,title:&#39;title&#39;},
  methods:{
    handleClick(){
      // ...
    },
    handleChange(){
      // ...
    }
  },
  template:&#39;
    <child class="child-width" :a="a" b="1" :title="title">&#39;,

})

则在<child></child>在中,$props的值为{title:'title'}$props可以用于自组件和孙组件定义的props都相同的情况,如:

Vue.component(&#39;grand-child&#39;, {
  props: [&#39;a&#39;,&#39;b&#39;],
  template: &#39;<h3>{{ a + b}}</h3>&#39;
})

// child和grand-child都需要用到来自父组件的a与b的值时,
// 在child中可以通过v-bind="$props"迅速把a与b注入到grand-child里
Vue.component(&#39;child&#39;, {
  props: [&#39;a&#39;,&#39;b&#39;],
  template: `
  <div>
    {{a}}加{{b}}的和是:
    <grand-child v-bind="$props"/>
  </div>
  `
})

new Vue({
  template:&#39;
    <child class="child-width" :a="1" :b="2">&#39;,
})

3. 妙用函数式组件

函数式组件相比于一般的vue组件而言,最大的区别是非响应式的。它不会监听任何数据,也没有实例(因此没有状态,意味着不存在诸如createdmounted的生命周期)。好处是因只是函数,故渲染开销也低很多。

把开头的例子改成函数式组件,代码如下:

<script>
  export default {
    name: "anchor-header",
    functional: true, // 以functional:true声明该组件为函数式组件
    props: {
      level: Number,
      name: String,
      content: String,
    },
    // 对于函数式组件,render函数会额外传入一个context参数用来表示上下文,即替代this。函数式组件没有实例,故不存在this
    render: function (createElement, context) {
      const anchor = {
        props: {
          content: String,
          name: String,
        },
        template: &#39;<a :id="name" :href="`#${name}`"> {{content}}</a>&#39;,
      };
      const anchorEl = createElement(anchor, {
        props: {
          content: context.props.content, //通过context.props调用props传入的变量
          name: context.props.name,
        },
      });
      const el = createElement(`h${context.props.level}`, [anchorEl]);
      return el;
    },
  };
</script>

4. 妙用 Vue.config.devtools

其实我们在生产环境下也可以调用vue-devtools去进行调试,只要更改Vue.config.devtools配置既可,如下所示:

// 务必在加载 Vue 之后,立即同步设置以下内容
// 该配置项在开发版本默认为 `true`,生产版本默认为 `false`
Vue.config.devtools = true;

我们可以通过检测cookie里的用户角色信息去决定是否开启该配置项,从而提高线上 bug 查找的便利性。

5. 妙用 methods

Vue中的method可以赋值为高阶函数返回的结果,例如:

<script>
  import { debounce } from "lodash";

  export default {
    methods: {
      search: debounce(async function (keyword) {
        // ... 请求逻辑
      }, 500),
    },
  };
</script>

上面的search函数赋值为debounce返回的结果,也就是具有防抖功能的请求函数。这种方式可以避免我们在组件里要自己写一遍防抖逻辑。

这里有个例子sandbox,大家可以点进去看看经过高阶函数处理的method与原始method的效果区别,如下所示:

9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung

除此之外,method还可以定义为生成器,如果我们有个函数需要执行时很强调顺序,而且需要在data里定义变量来记录上一次的状态,则可以考虑用生成器。

例如有个很常见的场景:微信的视频通话在接通的时候会显示计时器来记录通话时间,这个通话时间需要每秒更新一次,即获取通话时间的函数需要每秒执行一次,如果写成普通函数则需要在data里存放记录时间的变量。但如果用生成器则能很巧妙地解决,如下所示:

<template>
  <div id="app">
    <h3>{{ timeFormat }}</h3>
  </div>
</template>

<script>
  export default {
    name: "App",
    data() {
      return {
        // 用于显示时间的变量,是一个HH:MM:SS时间格式的字符串
        timeFormat: "",
      };
    },
    methods: {
      genTime: function* () {
        // 声明存储时、分、秒的变量
        let hour = 0;
        let minute = 0;
        let second = 0;
        while (true) {
          // 递增秒
          second += 1;
          // 如果秒到60了,则分加1,秒清零
          if (second === 60) {
            second = 0;
            minute += 1;
          }
          // 如果分到60了,则时加1,分清零
          if (minute === 60) {
            minute = 0;
            hour += 1;
          }
          // 最后返回最新的时间字符串
          yield `${hour}:${minute}:${second}`;
        }
      },
    },
    created() {
      // 通过生成器生成迭代器
      const gen = this.genTime();
      // 设置计时器定时从迭代器获取最新的时间字符串
      const timer = setInterval(() => {
        this.timeFormat = gen.next().value;
      }, 1000);
      // 在组件销毁的时候清空定时器和迭代器以免发生内存泄漏
      this.$once("hook:beforeDestroy", () => {
        clearInterval(timer);
        gen = null;
      });
    },
  };
</script>

页面效果如下所示:

9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung

代码地址:https://codesandbox.io/s/jovial-williams-nkouf?file=/src/App.vue

但需要注意的是:method 不能是箭头函数

注意,不应该使用箭头函数来定义 method 函数 (例如 plus: () => this.a++)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined

6. 妙用 watch 的数组格式

很多开发者会在watch中某一个变量的handler)

🎜Dann unten Als Beispiel für den Code: 🎜
<script>
  export default {
    data() {
      return {
        value: "",
      };
    },
    methods: {
      fn1() {},
      fn2() {},
    },
    watch: {
      value: {
        handler() {
          fn1();
          fn2();
        },
        immediate: true,
        deep: true,
      },
    },
  };
</script>
🎜Der Wert von 🎜
  • attrs in <child></child> ist {a:1 ,b:"1"
  • Der Wert von listeners ist {change: handleChange}
🎜 Normalerweise können wir $attrs und $listeners für die Komponentenkommunikation verwenden, was effizienter ist, wenn es in sekundären Verpackungskomponenten verwendet wird, wie zum Beispiel: 🎜
<script>
  watch:{
      &#39;value&#39;:[
          {
              handler:function(){
                  fn1()
              },
              immediate:true
          },
          {
              handler:function(){
                  fn2()
              },
              immediate:true,
              deep:true
          }
      ]
  }
</script>
🎜Ein weiteres Beispiel: 🎜
this.value = this.$options.data().value;

🎜2. Clevere Verwendung von $props

🎜$porps wird zum Aufzeichnen von Daten verwendet von übergeordneten Komponenten Alle an die untergeordnete Komponente übergebenen Parameter, die von props erfasst werden und nicht class und style sind. Beispielsweise steht 🎜
<template>
  <div>
    <el-button @click="visible=!visible">打开弹窗</el-button>
    <el-dialog @open="initForm" title="个人资料" :visible.sync="visible">
      <el-form>
        <el-form-item label="名称">
          <el-input v-model="form.name"/>
        </el-form-item>
        <el-form-item label="性别">
          <el-radio-group v-model="form.gender">
            <el-radio label="male">男</el-radio>
            <el-radio label="female">女</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>

export default {
  name: "App",
  data(){
    return {
      visible: false,
      form: {
        gender: &#39;male&#39;,
        name: &#39;wayne&#39;
      }
    }
  },
  methods:{
    initForm(){
      this.form = this.$options.data().form
    }
  }
};
</script>
🎜 in <child></child> und der Wert von $props ist {title:'title'} . $props kann verwendet werden, wenn die von der Self-Komponente und der Enkelkomponente definierten props identisch sind, wie zum Beispiel: 🎜
Object.assign(this.$data, this.$options.data());
// 注意千万不要写成下面的样子,这样子就更改this.$data的指向。使得其指向另外的与组件脱离的状态
this.$data = this.$options.data();

🎜3 . Funktionskomponenten wunderbar nutzen

🎜Im Vergleich zu gewöhnlichen vue-Komponenten besteht der größte Unterschied zwischen Funktionskomponenten darin, dass sie nicht reagieren. Es hört keine Daten ab und hat keine Instanzen (also keinen Status, was bedeutet, dass es keinen Lebenszyklus wie erstellt, montiert) gibt. Der Vorteil besteht darin, dass der Rendering-Aufwand viel geringer ist, da es sich nur um eine Funktion handelt. 🎜🎜Ändern Sie das Beispiel am Anfang in eine funktionale Komponente. Der Code lautet wie folgt: 🎜
<el-select>
  <el-option
    v-for="item in options"
    v-once
    :key="item.value"
    :label="item.label"
    :value="item.value"
    >{{i}}</el-option
  >
</el-select>

🎜4 Verwenden Sie Vue.config.devtools

🎜Tatsächlich können Sie vue-devtools auch zum Debuggen in einer Produktionsumgebung aufrufen. Ändern Sie einfach die Konfiguration von Vue.config.devtools, wie unten gezeigt: 🎜
<template>
  <child @hook:mounted="removeLoading" />
</template>
🎜Wir können die Erkennung bestehenCookie werden verwendet, um zu entscheiden, ob dieses Konfigurationselement aktiviert werden soll, wodurch die Bequemlichkeit der Online-Fehlersuche verbessert wird. 🎜

🎜5. Nützliche Methoden

🎜method in Vue können hoch- Ebenenwerte Das von der Funktion zurückgegebene Ergebnis, zum Beispiel: 🎜
<script>
  export default {
    created() {
      const timer = setInterval(() => {
        // 更新逻辑
      }, 1000);
      // 通过$once和hook监听实例自身的beforeDestroy,触发该生命周期时清除定时器
      this.$once("hook:beforeDestroy", () => {
        clearInterval(timer);
      });
    },
  };
</script>
🎜Der obigen search-Funktion wird das von debounce zurückgegebene Ergebnis zugewiesen, bei dem es sich um die Anforderungsfunktion mit Anti-Shake handelt Funktion. Mit dieser Methode können wir vermeiden, dass wir die Anti-Shake-Logik selbst in die Komponente schreiben müssen. 🎜🎜Hier ist ein Beispiel Sandbox🎜, Sie können hineinklicken, um den Unterschied zwischen der von Funktionen höherer Ordnung verarbeiteten Methode und der ursprünglichen Methode zu sehen, wie unten gezeigt: 🎜🎜 9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung🎜🎜Andere Darüber hinaus kann method auch als 🎜generator definiert werden. Wenn wir eine Funktion haben, die ausgeführt werden muss, wird die Reihenfolge hervorgehoben und Variablen müssen in data zum Aufzeichnen Für den letzten Zustand können Sie die Verwendung eines Generators in Betracht ziehen. 🎜🎜Zum Beispiel gibt es ein sehr häufiges Szenario: Wenn ein WeChat-Videoanruf verbunden ist, wird ein Timer angezeigt, um die 🎜Anrufzeit aufzuzeichnen. Diese 🎜Anrufzeit muss jede Sekunde aktualisiert werden , also get 🎜 Die Aufrufzeit-Funktion muss einmal pro Sekunde ausgeführt werden. Wenn sie als normale Funktion geschrieben wird, muss die Variable, die die Zeit aufzeichnet, in data gespeichert werden. Aber wenn man einen Generator verwendet, lässt sich das sehr geschickt lösen, wie unten gezeigt: 🎜rrreee🎜Der Seiteneffekt ist wie folgt: 🎜🎜9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung🎜
🎜Code-Adresse: https://codesandbox.io/s/jovial-williams-nkouf?file =/src /App.vue🎜
🎜🎜Aber es sollte beachtet werden: Methode kann keine Pfeilfunktion sein🎜
🎜Beachten Sie, dass Pfeilfunktionen nicht verwendet werden sollten um die Funktion methode zu definieren (z. B. plus: () => this.a++). Der Grund dafür ist, dass die Pfeilfunktion den Kontext des übergeordneten Bereichs bindet, sodass this nicht wie erwartet auf die Vue-Instanz verweist und this.a ist undefiniert code>. 🎜

🎜6 Verwenden Sie das Array-Format von watch

🎜Viele Entwickler verwenden ein bestimmtes in watch Im handler der Variablen werden mehrere Operationen aufgerufen, wie unten gezeigt: 🎜
<script>
  export default {
    data() {
      return {
        value: "",
      };
    },
    methods: {
      fn1() {},
      fn2() {},
    },
    watch: {
      value: {
        handler() {
          fn1();
          fn2();
        },
        immediate: true,
        deep: true,
      },
    },
  };
</script>

虽然fn1fn2都需要在value变动的时候调用,但两者的调用时机可能不同。fn1可能仅需要在deepfalse的配置下调用既可。因此,Vuewatch的值添加了Array类型来针对上面所说的情况,如果用watchArray的写法处理可以写成下面这种形式:

<script>
  watch:{
      &#39;value&#39;:[
          {
              handler:function(){
                  fn1()
              },
              immediate:true
          },
          {
              handler:function(){
                  fn2()
              },
              immediate:true,
              deep:true
          }
      ]
  }
</script>

7. 妙用$options

$options是一个记录当前Vue组件的初始化属性选项。通常开发中,我们想把data里的某个值重置为初始化时候的值,可以像下面这么写:

this.value = this.$options.data().value;

这样子就可以在初始值由于需求需要更改时,只在data中更改即可。

这里再举一个场景:一个el-dialog中有一个el-form,我们要求每次打开el-dialog时都要重置el-form里的数据,则可以这么写:

<template>
  <div>
    <el-button @click="visible=!visible">打开弹窗</el-button>
    <el-dialog @open="initForm" title="个人资料" :visible.sync="visible">
      <el-form>
        <el-form-item label="名称">
          <el-input v-model="form.name"/>
        </el-form-item>
        <el-form-item label="性别">
          <el-radio-group v-model="form.gender">
            <el-radio label="male">男</el-radio>
            <el-radio label="female">女</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>

export default {
  name: "App",
  data(){
    return {
      visible: false,
      form: {
        gender: &#39;male&#39;,
        name: &#39;wayne&#39;
      }
    }
  },
  methods:{
    initForm(){
      this.form = this.$options.data().form
    }
  }
};
</script>

每次el-dialog打开之前都会调用其@open中的方法initForm,从而重置form值到初始值。如下效果所示:

9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung

以上代码放在sanbox

如果要重置data里的所有值,可以像下面这么写:

Object.assign(this.$data, this.$options.data());
// 注意千万不要写成下面的样子,这样子就更改this.$data的指向。使得其指向另外的与组件脱离的状态
this.$data = this.$options.data();

8. 妙用 v-pre,v-once

v-pre

v-pre用于跳过被标记的元素以及其子元素的编译过程,如果一个元素自身及其自元素非常打,而又不带任何与Vue相关的响应式逻辑,那么可以用v-pre标记。标记后效果如下:

9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung

v-once

只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

对于部分在首次渲染后就不会再有响应式变化的元素,可以用v-once属性去标记,如下:

<el-select>
  <el-option
    v-for="item in options"
    v-once
    :key="item.value"
    :label="item.label"
    :value="item.value"
    >{{i}}</el-option
  >
</el-select>

如果上述例子中的变量options很大且不会再有响应式变化,那么如例子中用上v-once对性能有提升。

9. 妙用 hook 事件

如果想监听子组件的生命周期时,可以像下面例子中这么做:

<template>
  <child @hook:mounted="removeLoading" />
</template>

这样的写法可以用于处理加载第三方的初始化过程稍漫长的子组件时,我们可以加loading动画,等到子组件加载完毕,到了mounted生命周期时,把loading动画移除。

初次之外hook还有一个常用的写法,在一个需要轮询更新数据的组件上,我们通常在created里开启定时器,然后在beforeDestroy上清除定时器。而通过hook,开启和销毁定时器的逻辑我们都可以在created里实现:

<script>
  export default {
    created() {
      const timer = setInterval(() => {
        // 更新逻辑
      }, 1000);
      // 通过$once和hook监听实例自身的beforeDestroy,触发该生命周期时清除定时器
      this.$once("hook:beforeDestroy", () => {
        clearInterval(timer);
      });
    },
  };
</script>

像上面这种写法就保证了逻辑的统一,遵循了单一职责原则。

(学习视频分享:web前端开发编程基础视频

Das obige ist der detaillierte Inhalt von9 Vue-Tipps zur Verbesserung der Entwicklungseffizienz und -leistung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen