Maison  >  Article  >  interface Web  >  Le processus de mise en œuvre du filtrage dynamique des données du projet Vue

Le processus de mise en œuvre du filtrage dynamique des données du projet Vue

不言
不言original
2018-09-08 17:39:351326parcourir

Le contenu de cet article concerne le processus de mise en œuvre du filtrage dynamique des données du projet Vue. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Ce problème est un scénario réel que j'ai rencontré en travaillant sur un projet Vue. Voici un compte rendu de mes réflexions après avoir rencontré le problème et comment je l'ai finalement résolu (les anciens programmeurs ont de mauvais souvenirs-.-), et le processus Cela impliquera certains concepts de code source Vue tels que $mount, render watcher, etc. Si vous n'en savez pas grand-chose, vous pouvez jeter un œil à la série de lecture de code source Vue ~

Le problème est le suivant : la page est obtenue depuis le backend Les données sont constituées de clés telles que 0 et 1, et de la relation correspondante entre les valeurs représentées par cette clé, telles que 0-女 et 1-男, doit être obtenu depuis une autre interface de dictionnaire de données ; similaire à cette API :

{
  "SEX_TYPE": [
    { "paramValue": 0, "paramDesc": "女" },
    { "paramValue": 1, "paramDesc": "男" }
  ]
}

Ensuite si la vue obtient 0, elle doit trouver sa description dans le dictionnaire et l'afficher ; l'histoire commence ci-dessous

1. Réflexion

Certaines personnes disent que ce n'est pas ce que le filtre filter devrait faire. Utilisez simplement Vue.filter directement. attendre le retour de l'interface du dictionnaire de données asynchrone avant de pouvoir l'obtenir. Si c'est le cas $mount Lorsque ce filtre n'est pas trouvé, cela provoquera des erreurs qui affecteront le rendu ultérieur (écran blanc et erreur non définie

J'ai deux solutions en tête :

  1. Changer l'interface en synchronisation et obtenir l'interface du dictionnaire de données de manière synchrone dans le hook

    ou beforeCreate pour garantir que le filtre enregistré peut être obtenu sur created pour garantir le timing, mais cela bloquera le montage prolonge la durée de l'écran blanc, il n'est donc pas recommandé $mount

  2. modifie l'enregistrement du filtre en asynchrone, et informe

    de se mettre à jour après avoir obtenu le filtre, afin que la propre réponse de la vue puisse être utilisée. Mettez à jour la vue de manière standardisée sans bloquer le rendu, cette méthode est donc initialement adoptée ci-dessous. render watcher

2. Implémentation

Étant donné que le filtre appartient à Asset_types, il existe plusieurs conclusions sur la chaîne d'accès des Asset_types dans les instances Vue pour des pratiques de code spécifiques, veuillez vous référer à : Codepen - test de filtre

  1. comprend asset_types, filters et components Tous les directives suivants seront remplacés par les précédents asset_types<.>

  2. dans le composant enfant ne peut pas accéder à

    dans le composant parent, mais il peut accéder au asset_types enregistré globalement monté sur asset_types, qui correspond au code source src/core /util/ options.js$root.$options.asset_types.__proto__asset_types

  3. Méthode d'enregistrement globale Vue.asset_types, par exemple, lesasset_types enregistrés par Vue.filters seront montés sur le
  4. de l'instance racine (

    d'autres instances), et hérité de toutes les instances Vue créées dans le futur, c'est-à-dire que toutes les instances Vue créées dans le futur peuvent accéder au composant $root$options.asset_types.__proto__

  5. . slot est limité à l'endroit où il est défini, et c'est-à-dire que dans le composant dans lequel il est défini, le
  6. du composant parent n'est pas accessible, mais le

    asset_typesasset_types

    est accessible de la même manière, car le
  7. dans main.js L'instance 🎜> est l'instance racine, et le
  8. qui y est enregistré sera monté sur

    au lieu de new Vue()asset_types$root.$options.asset_types$root.$options.asset_types.__proto__

    Selon les conclusions ci-dessus, vous pouvez commencer à coder ~
2.1 En utilisant les filtres du composant racine

Donc, la première chose que je considère consiste à monter le filtre à enregistrer sur le composant racine, afin que d'autres composants puissent obtenir l'enregistrement en accédant à

filter, l'implémentation ici :

$rootRegister filter js

<template>
  <p>
    {{ rootFilters( sexVal )}}
  </p>
</template>
 
<script type=&#39;text/javascript&#39;>
  import Vue from 'vue'
  import { registerFilters } from 'utils/filters'
 
  export default {
    data() {
      return {
        sexVal: 1  // 性别
      }
    },
    methods: {
      /* 根组件上的过滤器 */
      rootFilters(val, id = 'SEX_TYPE') {
        const mth = this.$root.$options.filters[id]
        return mth && mth(val) || val
      }
    },
    created() {
      // 把根组件中的filters响应式化
      Vue.util.defineReactive(this.$root.$options, 'filters', this.$root.$options.filters)
    },
    mounted() {
      registerFilters.call(this)
        .then(data =>
          // 这里获取到数据字典的data
        )
    }
  }
</script>

Cela rend les filtres sur le composant racine réactifs, et lors du rendu, car la méthode

accède à
// utils/filters
 
import * as Api from 'api'
 
/**
* 获取并注册过滤器
* 注册在$root.$options.filters上不是$root.$options.filters.__proto__上
* 注意这里的this是vue实例,需要用call或apply调用
* @returns {Promise}
*/
export function registerFilters() {
  return Api.sysParams()            // 获取数据字典的Api
    .then(({ data }) => {
      Object.keys(data).forEach(T =>
        this.$set(this.$root.$options.filters, T, val => {
          const tar = data[T].find(item => item['paramValue'] === val)
          return tar['paramDesc'] || ''
        })
      )
      return data
    })
    .catch(err => console.error(err, ' in utils/filters.js'))
}
qui a été réactif lors de la création, donc lorsque les données obtenues de manière asynchrone sont affectées à

, cela se déclenchera le re-rendu du render watcher de ce composant, puis obtenir rootFilters$root.$options.filters Alors pourquoi ne pas l'enregistrer directement avec la méthode Vue.filter ici, car $root.$options.filters ne peut pas surveiller les modifications des données sur rootFilters, et le Vue.filter global est Le filtre est enregistré sur le composant racine

, il est donc impossible de répondre à ses modifications.

Object.definePropertyLe code ici peut être encore amélioré, mais il y a certains problèmes avec cette méthode. Tout d'abord, la méthode unstable sur __proto__ est utilisée ici. De plus, on peut voir partout en cours d'utilisation que <.> accède ainsi aux propriétés internes de l'instance vue. La situation, peu civilisée, est également déroutante à lire. $root.$options.asset_types.__proto__

Alors, lorsque ce projet a été terminé et en attente des tests, j'y ai pensé. Qui a dit que les filtres devaient être placés dans des filtres -. -, vous pouvez aussi utiliser mixin pour y parvenir

2.2 使用mixin

使用mixin要注意一点,因为vue中把data里所有以_$开头的变量都作为内部保留的变量,并不代理到当前实例上,因此直接this._xx是无法访问的,需要通过this.$data._xx来访问。

// mixins/sysParamsMixin.js
 
import * as Api from 'api'
 
export default {
  data() {
    return {
      _filterFunc: null,       // 过滤器函数
      _sysParams: null,        // 获取数据字典
      _sysParamsPromise: null  // 获取sysParams之后返回的Promise
    }
  },
  methods: {
    /* 注册过滤器到_filterFunc中 */
    _getSysParamsFunc() {
      const thisPromise = this.$data._sysParamsPromise
      return thisPromise || Api.sysParams()            // 获取数据字典的Api
        .then(({ data }) => {
          this.$data._filterFunc = {}
          Object.keys(data).forEach(paramKey =>
            this.$data._filterFunc[paramKey] = val => {        // 过滤器注册到_filterFunc中
              const tar = data[paramKey].find(item => item['paramValue'] === val)
              return tar['paramDesc'] || ''
            })
          return data
        })
        .catch(err => console.error(err, ' in src/mixins/sysParamsMixin.js'))
    },
 
    /* 按照键值获取单个过滤器 */
    _rootFilters(val, id = 'SEX_TYPE') {
      const func = this.$data._filterFunc
      const mth = func && func[id]
      return mth && mth(val) || val
    },
 
    /* 获取数据字典 */
    _getSysParams() {
      return this.$data._sysParams
    }
  },
  mounted() {
    this.$data._filterFunc ||
    (this.$data._sysParamsPromise = this._getSysParamsFunc())
  }
}

这里把Api的promise保存下来,如果其他地方还用到的话直接返回已经是resolved状态的promise,就不用再次去请求数据了。

那在我们的组件中怎么使用呢:

<template>
  <p>
    {{ _rootFilters( sexVal )}}
  </p>
</template>
 
<script type=&#39;text/javascript&#39;>
  import * as Api from 'api'
  import sysParamsMixin from 'mixins/sysParamsMixin'
 
  export default {
    mixins: [sysParamsMixin],
    data() {
      return { sexVal: 1 }
    },
    mounted() {
      this._getSysParamsFunc()
        .then(data =>
          // 这里获取到数据字典的data
        )
    }
  }
</script>

这里不仅注册了过滤器,而且也暴露了数据字典,以方便某些地方的列表显示,毕竟这是实际项目中常见的场景。

相关推荐:

如何在项目中使用Vue+animate过渡动画

Vue过滤器filters使用详解

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!

Déclaration:
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

Articles Liés

Voir plus