preface

Vue principle learning series, this period is mainly to learn the mode of vUE state-management, focusing on the aspect of instance sharing, instance sharing is the core of VUEX implementation.

Vue Principle learning series previous articles:

  • Series I: responsiveness
  • Series 2: Plugin plugin
  • Series (3) : Render function and Virtual Dom

⚡ Content Overview ⚡

  • Introduction to state-management
  • Props to pass
  • Objects share
  • The instance Shared
  • mutations
  • Functional programming

The following is based on VUe2

Introduction to state-management

What is a state?

The "thing/information" to remember is called a "state".

State is the information that a program uses to accomplish some task. It is the data or information that is changed or manipulated during the entire operation of the program. The “state” of the program at a given time is the data that the program is currently viewing or analyzing to perform the next step.

What is state management?

One of the biggest advantages of Vue, React, and Angular is that state is already transparently connected to the view, but the problem with these is that state can be easily propagated anywhere and changed anywhere. State is scattered across many components and interactions between components, and as our applications grow and become more complex, it becomes more difficult to track where state is stored and where state changes, and applications become more unpredictable.

To put it simply, front-end state management is a solution to the problem of how to store the code and how to centrally manage and distribute the state. Flux is the first idea about one-way data flow, which standardizes the way of data flow in Web applications and introduces the concept of front-end state management.

The following three sections are to sort out the data sharing methods in VUE

Props to pass

When we have two child components that need to share a state, we extract the shared state from the parent component and pass it to the child component via props.

For example, we want three counter components to share count<div id="app">
  <counter :count="count"></counter>
  <counter :count="count"></counter>
  <counter :count="count"></counter>
  <button @click="count++">increment</button>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    count: 0
  },
  components: {
    Counter: {
      props: {
        count: Number 
      },
      template: `<div>{{ count }}</div>`}}})</script>
Copy the code

Objects share

Data holds our common state by sharing objects.

Data in VUE generally has to be a function because most of the time we want each component instance to have its own independent data rather than all components of the same class sharing the same data.

<div id="app">
  <counter></counter>
  <counter></counter>
  <counter></counter>
  <button @click="inc">increment</button>
</div>

<script>
// state is the shared state
const state = {
  count: 0
}
const Counter = {
  data() {
    // Return to share status
    return state;
  },
  render(h) {
    return h('div'.this.count); }}new Vue({
  el: '#app'.components: {
    Counter
  },
  methods: {
    inc(){ state.count++; }}})</script>
Copy the code

The instance Shared

Using the Vue instance as a responsive data store or model, data changes are made in the Vue instance. The Vue instance state object itself is reactive by default, so we can reference it directly in other components without injecting it into data.

The benefit of instance sharing is that we hide the details of state changes while centrally managing state, centralizing the details of state changes in the instance as well. This central-model based state management is very similar to Vuex, whose core is based on vUE instances for responsiveness.

<div id="app">
  <counter></counter>
  <counter></counter>
  <counter></counter>
  <button @click="inc">increment</button>
</div>

<script>
// Vue shared instance
const state = new Vue({
  data: {
    count: 0
  },
  methods: {
    inc() {
      this.count++; }}})const Counter = {
  render: h= > h('div', state.count)
}
new Vue({
  el: '#app'.components: {
    Counter
  },
  methods: {
    inc(){ state.inc(); }}})</script>
Copy the code

mutations

In the above example share, our code has this section:

const state = new Vue({
    ...
    methods: {
      inc() {
        this.count++; }}})Copy the code

The concept of function in Vuex is called mutations and Actions. The difference between mutations and Actions lies in that mutations are used to change the state of state, which must be synchronous. Devtools needs to capture a snapshot of the former state and the latter state (to compare the differences before and after). Asynchronous function state changes are not traceable.

Actions can contain any asynchronous operation, but mutation is committed when a state change is required, rather than directly changing the state.

Actions and mutations are essentially designed to separate asynchronous code from state-changing code.

// Create a createStore function that emulates a simple version of vuex<div id="app">
  <counter></counter>
  <counter></counter>
  <counter></counter>
  <button @click="inc">increment</button>
</div>

<script>
function createStore({ state, mutations }) {
  return new Vue({
    data: {
      state
    },
    methods: {
      // Call the mutations method with commit
      commit(mutation) {
        if(! mutations.hasOwnProperty(mutation)) {throw new Error('Unknown mutation');
        }
        mutations[mutation](this.state); }}})}const store = createStore({
  state: { count: 0 },
  mutations: { inc (state) { state.count++; }}})const Counter = {
  render: h= > h('div', store.state.count)
}

new Vue({
  el: '#app'.components: {
    Counter
  },
  methods: {
    inc() {
      store.commit('inc'); }}})</script>
Copy the code

Functional programming

Functional programming is a programming paradigm

There is a lot of knowledge and concepts about javascript functional programming. This article is very detailed about javascript functional programming.

A pure function is defined as a function that, for the same input, always gets the same output, without any observable side effects, and independent of the state of the external environment.

In other words, a pure function definition has three characteristics:

  • deterministic: For the same input, always get the same output
  • No side effect: does not cause any observable side effects. Examples of visible side effects include modifying global objects or parameters passed by reference.
  • State that is independent of the external environment

Students who understand React and Redux will know that the premise of Redux is that the application state is immutable. Compared with Vuex accepting different mutations, Redux adopts actionType.

The core of Redux is a Reducer, which accepts the state and executes the action type, performs the appropriate action, and returns a new state copy.

// For example, use reducer to add and subtract
const reducer = (prevState, actionType) = > {
  switch(actionType) {
    case 'inc':
      return { count: prevState.count + 1; }
    case 'del':
      return { count: prevState.count - 1; }
    default:
      returnprevState; }}Copy the code
// Create a function app, accept el, model, view, actions, add, subtract, change button view<div id="app"></div>

<script>
function app({ el, model, view, actions }) {
  // Actions needs to be passed in the model argument, so we need to wrap actions and pass in the vue instance model
  const wrappedActions = {}
  Object.keys(actions).forEach(key= > {
    const originalAction = actions[key];
    wrappedActions[key] = () = > {
      // Accept the next model and update the original model
      constnextModel = originalAction(vm.model); vm.model = nextModel; }})const vm = new Vue({
    el,
    data: {
      model
    },
    render(h) {
      return view(h, this.data, wrappedActions)
    },
    methods: actions
  })
}

app({
  el: '#app'.model: {
    count: 0
  },
  actions: {
    inc: ({ count }) = > ({ count: count + 1 }),
    del: ({ count }) = > ({ count: count - 1})},view: (h, model, actions) = > h('div', { attrs: { id: 'app' }}, [
    model.count, ' ',
    ('button', { on: { click: actions.inc }}, '+'),
    ('button', { on: { click: actions.del }}, The '-')])})</script>
Copy the code

All of the above are based on personal understanding, welcome your comments.

Own front-end blog: Front-end learning Notes