Table of Contents
Why every component has
Home Web Front-end JS Tutorial A brief analysis of the source code content of VueX

A brief analysis of the source code content of VueX

Jul 20, 2018 pm 03:30 PM

Vuex is a state management pattern developed specifically for Vue.js applications. For single-page applications with many components and complex interactions, Vuex provides a convenient, accurate and predictable state management method to facilitate data sharing and modification between components.

The file structure is as follows

  • /module

  • /plugins

  • helpers.js

  • ##index.esm.js

  • index.js

  • store.js

  • util.js

util.js

Start with the simplest tool function.

find function

/**
 * Get the first item that pass the test
 * by second argument function
 *
 * @param {Array} list
 * @param {Function} f
 * @return {*}
 */
export function find (list, f) {
  return list.filter(f)[0]
}
Copy after login

Test case for find function

it('find', () => {
  const list = [33, 22, 112, 222, 43]
  expect(find(list, function (a) { return a % 2 === 0 })).toEqual(22)
})
Copy after login

Analysis:

    ##Use first
  • Assertion function f

    Filters list list, and finally takes the first element of the filtered list.

deepCopy function

/**
 * Deep copy the given object considering circular structure.
 * This function caches all nested objects and its copies.
 * If it detects circular structure, use cached copy to avoid infinite loop.
 *
 * @param {*} obj
 * @param {Array<Object>} cache
 * @return {*}
 */
export function deepCopy (obj, cache = []) {
  // just return if obj is immutable value
  if (obj === null || typeof obj !== &#39;object&#39;) {
    return obj
  }

  // if obj is hit, it is in circular structure
  const hit = find(cache, c => c.original === obj)
  if (hit) {
    return hit.copy
  }

  const copy = Array.isArray(obj) ? [] : {}
  // put the copy into cache at first
  // because we want to refer it in recursive deepCopy
  cache.push({
    original: obj,
    copy
  })

  Object.keys(obj).forEach(key => {
    copy[key] = deepCopy(obj[key], cache)
  })

  return copy
}
Copy after login
test case of deepCopy

  // 普通结构
  it(&#39;deepCopy: nornal structure&#39;, () => {
    const original = {
      a: 1,
      b: &#39;string&#39;,
      c: true,
      d: null,
      e: undefined
    }
    const copy = deepCopy(original)

    expect(copy).toEqual(original)
  })
  
  // 嵌套结构
  it(&#39;deepCopy: nested structure&#39;, () => {
    const original = {
      a: {
        b: 1,
        c: [2, 3, {
          d: 4
        }]
      }
    }
    const copy = deepCopy(original)

    expect(copy).toEqual(original)
  })
  
  // 循环引用结构
  it(&#39;deepCopy: circular structure&#39;, () => {
    const original = {
      a: 1
    }
    original.circular = original

    const copy = deepCopy(original)

    expect(copy).toEqual(original)
  })
Copy after login

Analysis:

    Function: Deep cloning function that supports circular references
  • The first if judgment
  • obj === null || typeof obj !== 'object'

    Judgment If it is not a reference type and is returned directly (the basic type is a value copy), it is also an exit from recursion.

  • The second judgment
  • hit

    is to judge whether it is a circular reference. Since it is a circular reference, there should be a copy cached in the cache, directly Get it from the cache to avoid making a duplicate copy again.

  • What is a circular reference? See the third test case
  • original.circular = original

    . The circular reference and the referenced content are the same. Caching is used to avoid duplication. Clone (the content is the same)

  • original.circular

    is a circular reference, original is a circular reference

  • First put
  • cope

    into cache. When recursing, if you encounter a circular reference, make sure there is a copy of the circularly referenced copy in the cache. , but copy must be a reference type.

  • Why
  • cope

    must be a reference type? Circular reference What is saved is the reference, not the content (the copy has not been completed at this time). The copy is not completed during the recursion. The copy is completed only after the recursion is completed, so that will be circularly referenced in the future## When the content of # changes (copying is completed), the content of circular reference changes simultaneously

    So
  • const copy = Array.isArray(obj) ? [] : {}
  • must be a reference type.

    Finally
  • Object.keys
  • You can traverse all key names of objects and arrays (only the properties of the instance are returned, excluding the prototype chain and Symbol) to implement recursive cloning.

    There are two exits, one is a basic type and the other is a circular reference.
  • ##forEachValue
/**
 * forEach for object
 */
export function forEachValue (obj, fn) {
  Object.keys(obj).forEach(key => fn(obj[key], key))
}
Copy after login

Test case

  it(&#39;forEachValue&#39;, () => {
    let number = 1

    function plus (value, key) {
      number += value
    }
    const origin = {
      a: 1,
      b: 3
    }

    forEachValue(origin, plus)
    expect(number).toEqual(5)
  })
Copy after login
Analysis:

A Function that traverses objects (supports objects and arrays)

  • fn(value, key)
  • But the first parameter of the callback function is the value, and the second parameter is the key Value
  • isObject
export function isObject (obj) {
  return obj !== null && typeof obj === &#39;object&#39;
}
Copy after login

Test Case

  it(&#39;isObject&#39;, () => {
    expect(isObject(1)).toBe(false)
    expect(isObject(&#39;String&#39;)).toBe(false)
    expect(isObject(undefined)).toBe(false)
    expect(isObject({})).toBe(true)
    expect(isObject(null)).toBe(false)
    expect(isObject([])).toBe(true)
    expect(isObject(new Function())).toBe(false)
  })
Copy after login
Resolution:

Determine whether it is an object. There is no judgment here whether it is a native object. Arrays also pass.

  • Because typeof null === 'object' must first determine whether it is null

  • ##isPromise

  • export function isPromise (val) {
      return val && typeof val.then === &#39;function&#39;
    }
    Copy after login
Test case

  it(&#39;isPromise&#39;, () => {
    const promise = new Promise(() => {}, () => {})
    expect(isPromise(1)).toBe(false)
    expect(isPromise(promise)).toBe(true)
    expect(isPromise(new Function())).toBe(false)
  })
Copy after login
Analysis:

Determine whether it is a Promise

  • First determine whether val is not undefined, and then You can judge val.then to avoid reporting errors

  • The basis for judgment is whether val.then is a function

  • assert

  • export function assert (condition, msg) {
      if (!condition) throw new Error(`[vuex] ${msg}`)
    }
    Copy after login
Test case:

  it(&#39;assert&#39;, () => {
    expect(assert.bind(null, false, &#39;Hello&#39;)).toThrowError(&#39;[vuex] Hello&#39;)
  })
Copy after login
Analysis:

Assertion function, assertion does not pass an Error

that throws a custom error message
  • index.js

    and
  • index.esm.js

index.js
import { Store, install } from &#39;./store&#39;
import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from &#39;./helpers&#39;

export default {
  Store,
  install,
  version: &#39;__VERSION__&#39;,
  mapState,
  mapMutations,
  mapGetters,
  mapActions,
  createNamespacedHelpers
}
Copy after login

index.esm.js

import { Store, install } from &#39;./store&#39;
import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from &#39;./helpers&#39;

export default {
  Store,
  install,
  version: &#39;__VERSION__&#39;,
  mapState,
  mapMutations,
  mapGetters,
  mapActions,
  createNamespacedHelpers
}

export {
  Store,
  install,
  mapState,
  mapMutations,
  mapGetters,
  mapActions,
  createNamespacedHelpers
}
Copy after login

Analysis:

The difference is that

index.esm.js

is better than
    index. js
  • There is an additional import mode

    import Vuex, { mapState } from 'index.esm.js'

    : There are two ways to import
  • import Vuex from 'index.js'

    : There is only one way to import
  • ##mixin.js<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export default function (Vue) { const version = Number(Vue.version.split(&amp;#39;.&amp;#39;)[0]) if (version &gt;= 2) { Vue.mixin({ beforeCreate: vuexInit }) } else { // override init and inject vuex init procedure // for 1.x backwards compatibility. const _init = Vue.prototype._init Vue.prototype._init = function (options = {}) { options.init = options.init ? [vuexInit].concat(options.init) : vuexInit _init.call(this, options) } } /** * Vuex init hook, injected into each instances init hooks list. */ function vuexInit () { const options = this.$options // store injection if (options.store) { this.$store = typeof options.store === &amp;#39;function&amp;#39; ? options.store() : options.store } else if (options.parent &amp;&amp; options.parent.$store) { this.$store = options.parent.$store } } }</pre><div class="contentsignin">Copy after login</div></div>Analysis: </p> <h4 id="Why-every-component-has">Why every component has </h4>\(store attribute, that is, every component can get\)<p>store</p> <ul class=" list-paddingleft-2"> <li><p>Vue2 directly uses the mixin and hook function beforeCreate, and Vue1 uses the appearance (decorator) mode to rewrite the Vue._init function. <span class="math inline"></span></p></li> <li>vuexInit<p> is to inject the globally registered store into the current component, before creating the component</p> </li> <li> <p><code>\(options are options of `new Vue(options)`,\)There is store

    in options
  • Since beforeCreate is the cycle hook of Vue, this points to the current component instance, so this.$storeThe store can be directly injected into the current component

  • All components are inherited from a global Vue, the global mixin component cycle hookbeforeCreate, so that each component Can be automatically injected into the store, that is, each component can get the global Vuenew Vue({ el: 'app', store, router }) directly through $store #store


Related recommendations:

Talk about me Understanding of vuex

Vue.js-vuex (state management)

The above is the detailed content of A brief analysis of the source code content of VueX. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How do I create and publish my own JavaScript libraries? How do I create and publish my own JavaScript libraries? Mar 18, 2025 pm 03:12 PM

Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.

How do I optimize JavaScript code for performance in the browser? How do I optimize JavaScript code for performance in the browser? Mar 18, 2025 pm 03:14 PM

The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

How do I debug JavaScript code effectively using browser developer tools? How do I debug JavaScript code effectively using browser developer tools? Mar 18, 2025 pm 03:16 PM

The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.

How do I use source maps to debug minified JavaScript code? How do I use source maps to debug minified JavaScript code? Mar 18, 2025 pm 03:17 PM

The article explains how to use source maps to debug minified JavaScript by mapping it back to the original code. It discusses enabling source maps, setting breakpoints, and using tools like Chrome DevTools and Webpack.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

Getting Started With Chart.js: Pie, Doughnut, and Bubble Charts Getting Started With Chart.js: Pie, Doughnut, and Bubble Charts Mar 15, 2025 am 09:19 AM

This tutorial will explain how to create pie, ring, and bubble charts using Chart.js. Previously, we have learned four chart types of Chart.js: line chart and bar chart (tutorial 2), as well as radar chart and polar region chart (tutorial 3). Create pie and ring charts Pie charts and ring charts are ideal for showing the proportions of a whole that is divided into different parts. For example, a pie chart can be used to show the percentage of male lions, female lions and young lions in a safari, or the percentage of votes that different candidates receive in the election. Pie charts are only suitable for comparing single parameters or datasets. It should be noted that the pie chart cannot draw entities with zero value because the angle of the fan in the pie chart depends on the numerical size of the data point. This means any entity with zero proportion

TypeScript for Beginners, Part 2: Basic Data Types TypeScript for Beginners, Part 2: Basic Data Types Mar 19, 2025 am 09:10 AM

Once you have mastered the entry-level TypeScript tutorial, you should be able to write your own code in an IDE that supports TypeScript and compile it into JavaScript. This tutorial will dive into various data types in TypeScript. JavaScript has seven data types: Null, Undefined, Boolean, Number, String, Symbol (introduced by ES6) and Object. TypeScript defines more types on this basis, and this tutorial will cover all of them in detail. Null data type Like JavaScript, null in TypeScript

See all articles