The filter paper

Individuals prefer to use computed, and filters are removed in Vue3

use

There are two ways to use it, the following two ways

! - in a pair of curly braces - > {{message | capitalize}}<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
Copy the code

Definition of filters

Filters can be defined in a component

filters: {
  capitalize: function (value) {
    if(! value)return ' '
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)}}Copy the code

Filters can also be defined globally

This is actually storage.

Vue.filter('capitalize'.function (value) {
  if(! value)return ' '
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)})Copy the code

The working principle of

The following code is essentially taking out the stored function

Define SRC /core/instance/render-helpers/ in the source code

The key function, resolveFilter

// resolve-filter.js
import {
  identity,
  resolveAsset
} from "core/util/index";

export function resolveFilter(id) {
    /* Call resolveAsset to get the return value or return identity */
  return resolveAsset(this.$options, "filters", id, true) || identity;
}
Copy the code
/** * Return same value */
export const identity = (_) = > _;
Copy the code
/* This function is called with four parameters: $options for the current instance, type for filters, and id for the current filter id */
export function resolveAsset (
  options: Object, type: string, id: string, warnMissing? : boolean) :any {
  
  /* ID must be a string */
  if (typeofid ! = ='string') {
    return
  }
  /* Get the object corresponding to type */
  const assets = options[type]

  // check local registration variations first
  /* Returns */ if it has this property
  if (hasOwn(assets, id)) return assets[id]
  /* Convert the middle line to hump and return */
  const camelizedId = camelize(id)
  if (hasOwn(assets, camelizedId)) return assets[camelizedId]
  /* converts to uppercase */
  const PascalCaseId = capitalize(camelizedId)
  if (hasOwn(assets, PascalCaseId)) return assets[PascalCaseId]
  // fallback to prototype chain
  /* If no prototype is found, raise a warning */
  const res = assets[id] || assets[camelizedId] || assets[PascalCaseId]
  if(process.env.NODE_ENV ! = ='production'&& warnMissing && ! res) { warn('Failed to resolve ' + type.slice(0, -1) + ':' + id,
      options
    )
  }
  return res
}
Copy the code

The _f function is an alias of the resolveFilter function, which fetches the corresponding filter function from the filters attribute in $options of the current instance according to the filter ID. The fetched filter function is executed later when the render function is executed.

Analytic filter

The following code is simply to take out the function to call

When you use it, there are two ways

<! - in a pair of curly braces - > {{message | capitalize}} <! -`v-bind`-- - ><div v-bind:id="rawId | formatId"></div>
Copy the code
function processAttrs (el) {
    // omit irrelevant code...
    if (bindRE.test(name)) { // v-bind
        // omit irrelevant code...
        value = parseFilters(value)
        // omit irrelevant code...
    }
    // omit irrelevant code...
}
Copy the code
export function parseText (text,delimiters){
    // omit irrelevant code...
    const exp = parseFilters(match[1].trim())
    // omit irrelevant code...
}
Copy the code

ParseFilters function analysis

ParseFilters function defined in the source code of the SRC/complier/parser/filter – parser. Js file

Is the role of the function of the incoming like ‘message | capitalize’ such a filter string into _f (” capitalize “) (the message)

/ * is the role of the function of the incoming like 'message | capitalize' such a filter string into _f (" capitalize ") (the message) * /
export function parseFilters (exp: string) :string {
  let inSingle = false
  let inDouble = false
  let inTemplateString = false
  let inRegex = false
  let curly = 0
  let square = 0
  let paren = 0
  let lastFilterIndex = 0
  let c, prev, i, expression, filters

  /* Iterate over each character of exp */
  for (i = 0; i < exp.length; i++) {
    prev = c
    c = exp.charCodeAt(i)
    if (inSingle) {
      if (c === 0x27&& prev ! = =0x5C) inSingle = false
    } else if (inDouble) {
      if (c === 0x22&& prev ! = =0x5C) inDouble = false
    } else if (inTemplateString) {
      if (c === 0x60&& prev ! = =0x5C) inTemplateString = false
    } else if (inRegex) {
      if (c === 0x2f&& prev ! = =0x5C) inRegex = false
    } else if (
      c === 0x7C && // pipe
      exp.charCodeAt(i + 1)! = =0x7C &&
      exp.charCodeAt(i - 1)! = =0x7C&&! curly && ! square && ! paren ) {if (expression === undefined) {
        // first filter, end of expression
        lastFilterIndex = i + 1
        expression = exp.slice(0, i).trim()
      } else {
        pushFilter()
      }
    } else {
      switch (c) {
        case 0x22: inDouble = true; break         // "
        case 0x27: inSingle = true; break         / / '
        case 0x60: inTemplateString = true; break / / `
        case 0x28: paren++; break                 / / (
        case 0x29: paren--; break                 // )
        case 0x5B: square++; break                / / /
        case 0x5D: square--; break                // ]
        case 0x7B: curly++; break                 / / {
        case 0x7D: curly--; break                 // }
      }
      if (c === 0x2f) { // /
        let j = i - 1
        let p
        // find first non-whitespace prev char
        for (; j >= 0; j--) {
          p = exp.charAt(j)
          if(p ! = =' ') break
        }
        if(! p || ! validDivisionCharRE.test(p)) { inRegex =true}}}}if (expression === undefined) {
    expression = exp.slice(0, i).trim()
  } else if(lastFilterIndex ! = =0) {
    pushFilter()
  }

  function pushFilter () {
    (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim())
    lastFilterIndex = i + 1
  }

  if (filters) {
    for (i = 0; i < filters.length; i++) {
      expression = wrapFilter(expression, filters[i])
    }
  }

  return expression
}
Copy the code

This function to receive a form such as’ message | capitalize ‘filter string as such, convert it into a final _f (” capitalize “) (the message) output. Inside the parseFilters function is the function that iterates through each character of the passed filter string, processing it differently depending on whether or not each character is a special character. Finally, from the passed filter string, the expression to be processed and an array of filters are parsed.

Finally, the parsed expression and filters array is constructed as a _f function call string by calling the wrapFilter function.