Implementation process of data dynamic filtering for Vue project

Source: Internet
Author: User
Tags filter register
This article gives you the content is about the Vue project data dynamic filtering implementation process, there is a certain reference value, the need for friends can refer to, I hope to help you.

The problem is the actual scenario that is being encountered in doing a Vue project, where I have a record of what I think and how I finally fix it (the old programmer has a bad memory.) -), the process will involve a number of Vue source concepts such as $mount , and render watcher so on, if you do not know well, you can see the Vue source Read series of articles ~

The problem is this: the data that the page gets from the background is the key, and the key 0 1 that represents the value 0-女 , for example, 1-男 is to be obtained from another data dictionary interface, similar to the API:

{"  sex_type": [    {"Paramvalue": 0, "Paramdesc": "Female"},    {"Paramvalue": 1, "Paramdesc": "Male"}  ]}

So if the view gets 0 it, it's going to find its description and show it from the dictionary ; the story begins.

1. Thinking

Some people say that this is not filter the filter to do, the direct vue.filter not on the line, but the problem is that the filter is to wait for the asynchronous data dictionary interface to return to get, if at $mount the time this filter is not found, Then the rendering (white screen and reporting undefined error) will result in the wrong effect.

There are two solutions that I think of:

    1. The interface becomes synchronous, in beforeCreate or created hook to obtain the data dictionary interface synchronously, to ensure that at $mount the time can get the registered filter, guaranteed timing, but this will block the mount, extended white screen time, so not recommended;

    2. The registration of the filter becomes asynchronous and notifies the update itself after getting the filter so that it render watcher can take advantage of Vue's own responsive update view, which does not block rendering, so this is the first approach.

2. Implement

Because filter belongs to Asset_types, there are several conclusions about the access chain asset_types in the Vue instance, and the specific code practice can be consulted as follows: Codepen-filter test

    1. asset_typesInclude,, filters components directives , and all of the following asset_types are replaced by their own previous items

    2. The child component asset_types does not have access to the parent component asset_types , but can access the mount on the global registration $root.$options.asset_types.__proto__ asset_types , which corresponds to the source code Src/core/util/options.js

    3. The global registration method Vue.asset_types, such as vue.filters registered asset_types is mounted on the root instance (other instances $root ) $options.asset_types.__proto__ and inherited by all subsequent Vue instances created, that is, All of the Vue instances created later have access to the

    4. The scope of a component's slot is limited to where it is defined, that is, the component it is defined in, not the parent component, asset_types but can access the globally definedasset_types

    5. Similarly, because the instance in Main.js new Vue() is the root instance, it is registered to be asset_types mounted on $root.$options.asset_types top rather than $root.$options.asset_types.__proto__

According to the above conclusions, we can begin to coding the ~

2.1 Filters using the root component

So the first thing I think about is to mount the filter to be registered to the root component, so that the other components can get to the registered filter by accessing it $root , the implementation here:

<template>  <p>    {rootfilters (sexval)}}  </p></template> <script type= ' text /javascript ' >  import Vue from ' vue '  import {registerfilters} from ' utils/filters '   export default {    Data () {      return {        sexval:1  //Sex      }    },    methods: {/      * filter on the root component */      rootfilters ( val, id = ' Sex_type ') {        const MTH = this. $root. $options. Filters[id]        return mth && mth (val) | | val      }    },    created () {      ///filters in the root component responds      Vue.util.defineReactive (this. $root. $options, ' filters ', this. $root. $options. filters)    },    mounted () {      registerfilters.call (The)        . Then (data =          //Get data from the dictionary here        )    }  } </script>

JS to register Filter

Utils/filters Import * As API from ' API '/*** get and register filter * registered on $root. $options. Filters is not $root. $options. filters.__proto__ * Note that this is the Vue instance and needs to be called with call or Apply * @returns {Promise}*/export function registerfilters () {  return api.sysparams ()            //Get the API for the data dictionary    . Then ({data}) = {      Object.keys (data). ForEach (The. $set (this.        $root. $ Options.filters, T, val = {          Const TAR = data[t].find (item = item[' paramvalue ') = = = val)          return tar[' PARAMD Esc '] | |      return Data    })    . catch (Err = Console.error (err, ' in Utils/filters.js ')}

This makes the filters on the root component reactive and, when rendered, because it is accessed in a rootFilters method that has already been responded to in the created $root.$options.filters , triggers the component when the asynchronously acquired data is assigned to $root.$options.filters render Watcher re-rendering, at rootFilters this time to obtain the method when the filter can be taken;

Then why not use the Vue.filter method to register directly, because the Object.defineProperty data can not be monitored __proto__ changes, and the global Vue.filter is to register the filter on the root component $root.$options.asset_types.__proto__ , so its changes can not be responded to.

The code here can be further improved, but this method has some problems, first of all, the use of an unstable Vue.util method, and in the use of this.$root.$options such access to the Vue instance inside the properties of the case, not too civilized, read also confusing.

So I thought about it when the project was done waiting to be tested, and who said that the filter would have to be in the filters. -You can also use Mixin to implement

2.2 Using Mixin

One thing to note about using Mixin is that, since all _ $ of the variables in the data in Vue are reserved as internal variables, they are not proxied to the current instance and are therefore directly inaccessible this._xx and need this.$data._xx to be accessed through.

Mixins/sysparamsmixin.js Import * As API from ' API ' export default {data () {return {_filterfunc:null, Filter function _sysparams:null,//Get Data dictionary _sysparamspromise:null//Get Sysparams return after promise}}, Meth ODS: {/* Register filter to _filterfunc */_getsysparamsfunc () {Const Thispromise = this. $data. _sysparamspromise ret Urn Thispromise | | Api.sysparams ()//Get the data Dictionary API. Then ({data}) = {this. $data. _filterfunc = {} OBJ Ect.keys (data). ForEach (Paramkey = $data. _filterfunc[paramkey] = val + = {//filter registered to _filterfun C in Const TAR = data[paramkey].find (item = item[' paramvalue ') = = = val) return tar[' Paramdesc ' ] || Return data}). catch (Err = Console.error (err, ' in src/mixins/sysparamsmixin. JS ')},/* Gets a single filter by key value */_rootfilters (val, id = ' Sex_type ') {const FUNC = this. $data. _filterfunc CoNST mth = func && Func[id] return mth && mth (val) | | Val},/* Gets the data dictionary */_getsysparams () {return this. $data. _sysparams}}, mounted () {this. $data. _fil    Terfunc | | (this. $data. _sysparamspromise = This._getsysparamsfunc ())}}

ApiSave the promise here, if other places also use the words directly return is already resolved the state of the promise, there is no need to request data again.

How to use it in our components:

<template>  <p>    {_rootfilters (sexval)}}  </p></template> <script type= ' Text/javascript ' >  import * As API from ' API '  import sysparamsmixin from ' mixins/sysparamsmixin '   export Default {    mixins: [Sysparamsmixin],    data () {      return {sexval:1}    },    mounted () {      this._ Getsysparamsfunc ()        . Then (data =          //Here Gets the database in the dictionary        )    }  }</script>

Not only did the filter register, but it also exposed the data dictionary to make it easier to display the list in some places, which is a common scenario in real-world projects.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.