Maison > interface Web > Voir.js > Partagez quelques conseils pratiques utilisés dans les projets Vue

Partagez quelques conseils pratiques utilisés dans les projets Vue

青灯夜游
Libérer: 2020-09-28 18:01:17
avant
2518 Les gens l'ont consulté

Partagez quelques conseils pratiques utilisés dans les projets Vue

Dans le processus de développement de Vue, nous rencontrons souvent des problèmes d'une sorte ou d'une autre, et nous devons ensuite rester bloqués pendant longtemps. le problème est résolu, on découvre les problèmes d’origine, je n’ai toujours pas maîtrisé les détails. Aujourd'hui, l'éditeur a compilé quelques conseils pratiques qui seront utilisés dans le projet. J'espère que cela pourra vous aider qui travaillez dur pour gagner de l'argent. Les règles du monde sont les suivantes : aimer d’abord, lire plus tard et vivre des rencontres amoureuses sans fin.

Les données ne répondent pas. Il peut y avoir un problème d'utilisation

Un ami m'a envoyé un morceau de code il y a quelques jours et m'a dit que Vue a un bug, il l'a clairement écrit bien, pourquoi les données ne répondent-elles pas ? Ce doit être un bug de Vue ? Je sentais qu'il était plus puissant que You Yuxi et qu'il ne pouvait pas atteindre un niveau supérieur, alors je l'ai ignoré. Mais il est vrai que nous rencontrons parfois un manque de réponse des données pendant le développement, alors que devons-nous faire ? Par exemple, le code suivant :

<template>
  <div>
    <div>
      <span>用户名: {{ userInfo.name }}</span>
      <span>用户性别: {{ userInfo.sex }}</span>
      <span v-if="userInfo.officialAccount">
        公众号: {{ userInfo.officialAccount }}
      </span>
    </div>
    <button @click="handleAddOfficialAccount">添加公众号</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      userInfo: {
        name: &#39;子君&#39;,
        sex: &#39;男&#39;
      }
    }
  },
  methods: {
    // 在这里添加用户的公众号
    handleAddOfficialAccount() {
      this.userInfo.officialAccount = &#39;前端有的玩&#39;
    }
  }
}
</script>
Copier après la connexion

Dans le code ci-dessus, nous espérons ajouter l'attribut de compte officiel aux informations de l'utilisateur, mais via this.userInfo.officialAccount = 'Certaines personnes peuvent jouer sur le front end' Après l'avoir ajouté, cela ne prend pas effet Pourquoi ?

En effet, à l'intérieur de Vue, la réponse des données se fait en utilisant Object.definePrototype pour écouter chaque clé de l'objet getter,< La méthode 🎜 >Setter est implémentée, mais seuls les attributs existants peuvent être surveillés via cette méthode. Les attributs nouvellement ajoutés ne peuvent pas être surveillés, mais je souhaite simplement les surveiller. Éditeur, veuillez me dire quoi faire. L'éditeur ci-dessous propose quatre méthodes. S'il existe d'autres méthodes, veuillez me le dire dans la zone de commentaires ci-dessous.

1. Définir les attributs à ajouter au préalable dans

data

Par exemple, pour le compte public ci-dessus, je peux le définir dans advance in

userInfo y est défini, de sorte qu'il ne s'agit pas d'un nouvel attribut, tout comme le suivant

data() {
    return {
      userInfo: {
        name: &#39;子君&#39;,
        sex: &#39;男&#39;,
        // 我先提前定义好
        officialAccount: &#39;&#39;
      }
    }
  }
Copier après la connexion

2 Remplacez directement

userInfo<🎜. > Bien que je ne puisse pas ajouter de nouveaux attributs à

userInfo

, car userInfo a déjà été défini, je peux simplement modifier la valeur de userInfo directement , vous pouvez donc également écrire comme suit

3. Utilisez

Vue.set<. 🎜>En fait, les deux méthodes ci-dessus sont un peu délicates. En fait, pour les nouveaux attributs, Vue

fournit officiellement une nouvelle méthode

Vue.set pour résoudre le problème de l'ajout de nouveaux attributs. . Déclencher la réponse des données. Définition de la méthode Vue.set

/**
* target 要修改的对象
* prpertyName 要添加的属性名称
* value 要添加的属性值
*/
Vue.set( target, propertyName, value )
Copier après la connexion

Le code ci-dessus peut être utilisé en utilisant Vue.set

Modifiez-le en

import Vue from &#39;vue&#39;

// 在这里添加用户的公众号
handleAddOfficialAccount() {
  Vue.set(this.userInfo,&#39;officialAccount&#39;, &#39;前端有的玩&#39;)
}
Copier après la connexion
, mais chaque fois que vous souhaitez utiliser la méthode set

, vous devez introduire

Vue, ce qui est très gênant, donc pour le par souci de simplicité, Vue a monté la méthode set sur la chaîne prototype de Vue, c'est-à-dire , afin qu'elle puisse être utilisée directement à l'intérieur du Composant VueVue.prototype.$set = Vue.setthis.$set remplace Vue.set

this.$set(this.userInfo,&#39;officialAccount&#39;, &#39;前端有的玩&#39;)
Copier après la connexion
L'éditeur a constaté que de nombreux étudiants ne savent pas quand utiliser Vue.set

. En fait, vous devez uniquement utiliser

Vue, set lorsque l'attribut que vous souhaitez attribuer n'a pas été défini. Il n'est généralement pas nécessaire à d'autres moments. 4. Utilisez

$forceUpdate

Je pense que l'existence de empêche de nombreux développeurs front-end de prêter attention aux échanges bidirectionnels. liaison de données. Le principe est fixe, car peu importe quand, après avoir modifié

data

, l'appel de $forceUpdate$forceUpdate fera restituer le composant Vue, bug n'existera pas. Mais en fait, cette méthode n’est pas recommandée car elle entraînerait une consommation inutile de performances. Méthodes spécifiques aux tableaux

En fait, il ne s'agit pas seulement d'objets, les tableaux ont aussi des situations où ils ne répondent pas après modification des données, comme le code suivant

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item">
        {{ item }}
      </li>
    </ul>
    <button @click="handleChangeName">修改名称</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: [&#39;张三&#39;, &#39;李四&#39;]
    }
  },
  methods: {
    // 修改用户名称
    handleChangeName() {
      this.list[0] = &#39;王五&#39;
    }
  }
}
</script>
Copier après la connexion

Le code ci-dessus espère que le changement du nom de Zhang San en Wang Wu ne prendra pas effet, car

Vue

ne peut pas détecter les tableaux modifiés suivants :

    Quand. vous définissez un élément directement à l'aide d'un index, par exemple :
  • this.list[index] = newValue

  • Modifiez la propriété
  • length, par exemple : this.list.length = 0

所以在上例中通过this.list[0] = '王五' 是无法触发数据响应的,那应该怎么办呢?像上面提到的Vue.set$forceUpdate都可以解决这个问题,比如Vue.set可以这样写

Vue.set(this.list,0,&#39;王五&#39;)
Copier après la connexion

除了那些方法之外,Vue还针对数组提供了变异方法

在操作数组的时候,我们一般会用到数据提供的许多方法,比如push,pop,splice等等,在Vue中调用数组上面提供的这些方法修改数组的值是可以触发数据响应的,比如上面的代码改为以下代码即可触发数据响应

this.list.splice(0,1,&#39;王五&#39;)
Copier après la connexion

实际上,如果Vue仅仅依赖gettersetter,是无法做到在数组调用push,pop等方法时候触发数据响应的,因此Vue实际上是通过劫持这些方法,对这些方法进行包装变异来实现的。

Vue对数组的以下方法进行的包装变异:

  • push
  • pop
  • shift
  • unshift
  • splice
  • sort
  • reverse

所以在操作数组的时候,调用上面这些方法是可以保证数据可以正常响应,下面是Vue源码中包装数组方法的代码:

var original = arrayProto[method];
  def(arrayMethods, method, function mutator () {
    // 将 arguments 转换为数组
    var args = [], len = arguments.length;
    while ( len-- ) args[ len ] = arguments[ len ];
    var result = original.apply(this, args);
    // 这儿的用法同dependArray(value),就是为了取得dep
    var ob = this.__ob__;
    var inserted;
    switch (method) {
      case &#39;push&#39;:
      case &#39;unshift&#39;:
        inserted = args;
        break
      case &#39;splice&#39;:
        inserted = args.slice(2);
        break
    }
    // 如果有新的数据插入,则插入的数据也要进行一个响应式
    if (inserted) { ob.observeArray(inserted); }
   // 通知依赖进行更新
    ob.dep.notify();
    return result
  });
Copier après la connexion

文本格式化,filter更简单

使用filter 简化逻辑

我想把时间戳显示成yyyy-MM-DD HH:mm:ss的格式怎么办?是需要在代码中先将日期格式化之后,再渲染到模板吗?就像下面这样

<template>
  <div>
    {{ dateStr }}
    <ul>
      <li v-for="(item, index) in getList" :key="index">
        {{ item.date }}
      </li>
    </ul>
  </div>
</template>
<script>
import { format } from &#39;@/utils/date&#39;
export default {
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  },
  computed: {
    dateStr() {
      return format(this.date, &#39;yyyy-MM-DD HH:mm:ss&#39;)
    },
    getList() {
      return this.list.map(item => {
        return {
          ...item,
          date: format(item.date, &#39;yyyy-MM-DD HH:mm:ss&#39;)
        }
      })
    }
  }
}
</script>
Copier après la connexion

像上面的写法,针对每一个日期字段都需要调用format,然后通过计算属性进行转换?这时候可以考虑使用Vue提供的filter去简化

<template>
  <div>
    <!--使用过滤器-->
    {{ dateStr | formatDate }}
    <ul>
      <li v-for="(item, index) in list" :key="index">
        <!--在v-for中使用过滤器-->
        {{ item.date | formatDate }}
      </li>
    </ul>
  </div>
</template>
<script>
import { format } from &#39;@/utils/date&#39;
export default {
  filters: {
    formatDate(value) {
      return format(value, &#39;yyyy-MM-DD HH:mm:ss&#39;)
    }
  },
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  }
}
</script>
Copier après la connexion

通过上面的修改是不是就简单多了

注册全局filter

有些过滤器使用的很频繁,比如上面提到的日期过滤器,在很多地方都要使用,这时候如果在每一个要用到的组件里面都去定义一遍,就显得有些多余了,这时候就可以考虑Vue.filter注册全局过滤器

对于全局过滤器,一般建议在项目里面添加filters目录,然后在filters目录里面添加

// filters\index.js

import Vue from &#39;vue&#39;
import { format } from &#39;@/utils/date&#39;

Vue.filter(&#39;formatDate&#39;, value => {
  return format(value, &#39;yyyy-MM-DD HH:mm:ss&#39;)
})
Copier après la connexion

然后将filters里面的文件引入到main.js里面,这时候就可以在组件里面直接用了,比如将前面的代码可以修改为

<template>
  <div>
    <!--使用过滤器-->
    {{ dateStr | formatDate }}
    <ul>
      <li v-for="(item, index) in list" :key="index">
        <!--在v-for中使用过滤器-->
        {{ item.date | formatDate }}
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  }
}
</script>
Copier après la connexion

是不是更简单了

开发了插件库,来安装一下

在使用一些UI框架的时候,经常需要使用Vue.use来安装, 比如使用element-ui时候,经常会这样写:

import Vue from &#39;vue&#39;;
import ElementUI from &#39;element-ui&#39;;
import &#39;element-ui/lib/theme-chalk/index.css&#39;;
Vue.use(ElementUI,{size: &#39;small&#39;});
Copier après la connexion

使用了Vue.use之后,element-ui就可以直接在组件里面使用了,好神奇哦(呸,娘炮)。接下来我们实现一个简化版的element来看如何去安装。

了解Vue.use的用法

Vue.use是一个全局的方法,它需要在你调用 new Vue() 启动应用之前完成,Vue.use的参数如下

/**
* plugin: 要安装的插件 如 ElementUI
* options: 插件的配置信息 如 {size: &#39;small&#39;}
*/
Vue.use(plugin, options)
Copier après la connexion

模拟element-ui的安装逻辑

想一下,使用Vue.use(ElementUI,{size: 'small'}) 之后我们可以用到哪些element-ui提供的东西

// 这个是一个按钮组件
import Button from &#39;@/components/button&#39;

// loading 指令
import loadingDirective from &#39;@/components/loading/directive&#39;

// loading 方法
import loadingMethod from &#39;@/components/loading&#39;

export default {
  /**
   * Vue.use 需要插件提供一个install方法
   * @param {*} Vue Vue
   * @param {*} options 插件配置信息
   */
  install(Vue, options) {
    console.log(options)
    // 将组件通过Vue.components 进行注册
    Vue.components(Button.name, Button)

    // 注册全局指令
    Vue.directive(&#39;loading&#39;, loadingDirective)

    // 将loadingMethod 挂载到 Vue原型链上面,方便调用
    Vue.prototype.$loading = loadingMethod
  }
}
Copier après la connexion

通过上面的代码,已经实现了一个丐版的element-ui插件,这时候就可以在main.js里面通过Vue.use进行插件安装了。大家可能会有疑问,为什么我要用这种写法,不用这种写法我照样可以实现功能啊。小编认为这种写法有两个优势

  • 标准化,通过提供一种统一的开发模式,无论对插件开发者还是使用者来说,都有一个规范去遵循。

  • 插件缓存,Vue.use 在安装插件的时候,会对插件进行缓存,即一个插件如果安装多次,实际上只会在第一次安装时生效。

插件的应用场景

  • 添加全局方法或者 property。

  • 添加全局资源:指令/过滤器/过渡等。

  • 通过全局混入来添加一些组件选项。

  • 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

  • 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如element-ui

提高Vue渲染性能,了解一下Object.freeze

当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。但是这个过程实际上是比较消耗性能的,所以对于一些有大量数据但只是展示的界面来说,并不需要将property加入到响应式系统中,这样可以提高渲染性能,怎么做呢,你需要了解一下Object.freeze

Vue官网中,有这样一段话:这里唯一的例外是使用 Object.freeze(),这会阻止修改现有的 property,也意味着响应系统无法再_追踪_变化。这段话的意思是,如果我们的数据使用了Object.freeze,就可以让数据脱离响应式系统,那么该如何做呢?

比如下面这个表格,因为只是渲染数据,这时候我们就可以通过Object.freeze来优化性能

<template>
  <el-table :data="tableData" >
    <el-table-column prop="date" label="日期" width="180" />
    <el-table-column prop="name" label="姓名" width="180" />
    <el-table-column prop="address" label="地址" />
  </el-table>
</template>
<script>
export default {
  data() {
    const data = Array(1000)
      .fill(1)
      .map((item, index) => {
        return {
          date: &#39;2020-07-11&#39;,
          name: `子君${index}`,
          address: &#39;大西安&#39;
        }
      })
    return {
      // 在这里我们用了Object.freeze
      tableData: Object.freeze(data)
    }
  }
}
</script>
Copier après la connexion

有的同学可能会有疑问,如果我这个表格的数据是滚动加载的,你这样写我不就没法再给tableData添加数据了吗?是,确实没办法去添加数据了,但还是有办法解决的,比如像下面这样

export default {
  data() {
    return {
      tableData: []
    }
  },
  created() {
    setInterval(() => {
      const data = Array(1000)
        .fill(1)
        .map((item, index) => {
          // 虽然不能冻结整个数组,但是可以冻结每一项数据
          return Object.freeze({
            date: &#39;2020-07-11&#39;,
            name: `子君${index}`,
            address: &#39;大西安&#39;
          })
        })
      this.tableData = this.tableData.concat(data)
    }, 2000)
  }
}
Copier après la connexion

合理的使用Object.freeze,是可以节省不少渲染性能,特别对于IE浏览器,效果还是很明显的,赶快去试试吧。

最后如果你现在需要开发移动端项目,可以了解一下小编整理的一个开箱即用框架 vue-vant-base,也许可以帮到你哦

结语

不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特?梵高

相关推荐:

2020年前端vue面试题大汇总(附答案)

vue教程推荐:2020最新的5个vue.js视频教程精选

更多编程相关知识,请访问:编程入门!!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
vue
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal