ホームページ  >  記事  >  ウェブフロントエンド  >  Vueプロジェクトデータの動的フィルタリングの実装方法

Vueプロジェクトデータの動的フィルタリングの実装方法

不言
不言転載
2018-11-16 16:46:163925ブラウズ

この記事の内容は、Vue プロジェクト データの動的フィルタリングの実装方法に関するものです。必要な方は参考にしていただければ幸いです。

この問題は、私が Vue プロジェクトで作業中に遭遇した実際のシナリオです。ここでは、問題に遭遇した後の私の考えと、最終的にどのように解決したかを記録します (古いプログラマーには嫌な思い出があります)。
問題は次のとおりです:

ページが背景から取得したデータは、0や1などのキーと、このキーで表される値の対応関係(0-女性など)で構成されています。および 1-男性は、別のデータ ディクショナリ インターフェイスから取得されます。

类似于这样的Api:

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

次に、ビューが 0 を取得した場合、その説明をディクショナリから見つけて表示する必要があります。

1 . 思考

これはフィルターが行うべきことではないのではないかと言う人もいます。

しかし、問題は、このフィルターは、非同期データ ディクショナリ インターフェイス。$mount 時にこのフィルターが見つからない場合は、エラーが発生し、その後のレンダリングに影響します (白い画面と未定義のエラー)。 ##私が考えたこと。解決策は 2 つあります:

インターフェイスを同期に変更し、beforeCreate または created フックでデータ ディクショナリ インターフェイスを同期的に取得して、登録されたフィルターが確実に機能できるようにします。タイミングを確保するために $mounting 時に取得されますが、これによりマウントがブロックされ、白い画面時間が延長されるため、推奨されません。

    フィルターの登録を非同期に変更します。このようにして、vue 自体の応答性を使用して、レンダリングをブロックせずにビューを更新できるため、このメソッドは最初は
  • 2 で採用されます。実装
  • フィルターはasset_typesに属しているため、Vueインスタンスのasset_typesのアクセスチェーンについては次の結論があります。具体的なコードの実践については、「Codepen - フィルターテスト」を参照してください。

asset_types にはフィルター、コンポーネント、ディレクティブが含まれており、次のすべてのasset_types は以前のものに置き換えられます

asset_types 子コンポーネントのasset_types はアクセスできません親コンポーネントのasset_typesですが、root.$options.asset_types.__proto__の$asset_typesにグローバルに登録されたマウントにアクセスできます。これはソースコードsrc/core/util/options.js

に対応します。
    #Vue.filters によって登録されたメソッドなど、グローバルに登録されたメソッド Vue.asset_types は、ルート インスタンス (他のインスタンスの $root) の $options.asset_types.__proto__ にマウントされ、すべての Vue インスタンスによって継承されます。つまり、今後作成されるすべての Vue インスタンスは
  • コンポーネントのスロットのスコープは、コンポーネントが定義されている場所に制限されます。親コンポーネントのasset_typesにはアクセスできませんが、グローバルに定義されたasset_typesにはアクセスできます
  • #同様に、mainに新しいVue()インスタンスがあるためです。 js がルート インスタンスであり、そこに登録されているasset_types は、$ root.$options.asset_types ではなく $root.$options.asset_types にマウントされます。__proto__
  • 上記の結論に基づくと、 、コーディングを開始できます~
  • 2.1 ルート コンポーネントのフィルターを使用する

  • そこで、最初に検討するのは、ルート コンポーネントに登録するフィルターをマウントすることです。他のコンポーネントは、$root にアクセスすることで、登録されたフィルターを取得できます。
  • ここでの実装:

    <template>
      <div>
        {{ rootFilters( sexVal )}}
      </div>
    </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>
  • フィルターを登録するための JS
// 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,返回的是promise
    .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'))
}

これにより、rootFilters メソッドは $root にアクセスするため、ルート コンポーネントのフィルターが応答しやすくなり、レンダリング時にも動作します。リアクティブな $options.filters が作成されました。

したがって、非同期で取得されたデータが $root.$options.filters に割り当てられると、このコンポーネントのレンダー ウォッチャーの再レンダリングがトリガーされます。このとき、フィルターは rootFilters のときに取得できます。メソッドが取得されます;それでは、ここで Vue.filter メソッドを直接登録してみてはいかがでしょうか。

Object.defineProperty は __proto__ 上のデータの変更を監視できないためです。

グローバル Vue.filter はルート コンポーネント $root.$options.asset_types.__proto__ にフィルターを登録するため、その変更には応答できません。

ここでのコードはさらに改善することができますが、この方法にはいくつかの問題があります。まず、ここでは Vue.util の不安定な方法が使用されています。

さらに、使用中のあらゆる場所で this.$root.$options が vue インスタンスの内部プロパティにアクセスしているのがわかりますが、これはあまり文明的ではなく、読むのが混乱します。

それで、このプロジェクトが完了してテストを待っているときに、フィルターをフィルターの中に配置しなければならないなんて誰が言ったのかと思いました。 -、mixin を使用してそれを実現することもできます

2.2 mixin の使用

Vue はデータ内の _ と $ で始まるすべての変数を内部予約変数として扱うため、mixin を使用するときは注意してください。 。

は現在のインスタンスにプロキシしないため、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 { $data } = this
      return $data._sysParamsPromise || ($data._sysParamsPromise = Api.sysParams()
        .then(({ data }) => {
          this.$data._sysParams = data
          this.$data._filterFunc = {}
          Object.keys(data).forEach(paramKey =>
            this.$data._filterFunc[paramKey] = val => {
              const tar = data[paramKey].find(item => item['paramValue'] === val)
              return tar && 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
    }
  }
}

API の Promise をここに保存します。API が他の場所で使用される場合は、すでに解決済みの状態にある Promise が直接返されるため、データを再度リクエストする必要はありません。

さらに、他のインスタンスからのアクセスを容易にするために、ルート コンポーネントにマウントされます。

ルートコンポーネントでの使用方法:

// src/main.js

import sysParamsMixin from 'mixins/sysParamsMixin'

new Vue({
  el: '#app',
  mixins: [sysParamsMixin],
  render: h => h(App),
})

在需要用过滤器的组件中:

<template>
  <div>
    {{ $root._rootFilters( sexVal )}}
  </div>
</template>

<script type=&#39;text/javascript&#39;>
  export default {
    data() {
      return { sexVal: 1 }
    },
    mounted() {
      this.$root._getSysParamsFunc()
        .then(data =>
          // 这里获取到数据字典的data
        )
    }
  }
</script>

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

当然如果使用vuex更好,不过这里的场景个人觉得没必要用vuex,如果还有更好的方法可以讨论一下下啊~

以上がVueプロジェクトデータの動的フィルタリングの実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。