Cl8023.com Github unfinished…

component

The parent component communicates with the child component

The parent component communicates to the child component via props. In the parent component, the value in the child component can be read by this.$children. Props is a one-way binding and cannot be assigned to a child component.Copy the code

Create a single-file component

Create a folder common under SRC/Components to hold common components, and create a single-file component leftNavItem.vue under common.

<template>
  <div>
    {{ childMes }}
  </div>
</template>

<script>
  export default {
    name: 'LeftNav',
    props: ['childMes'],
  }
</script>

<style lang="scss">

</style>
Copy the code

The introduction of the component

In SRC/components/page/Blog. Vue (parent components) in introducing component LeftNavItem. Vue

<template> <div> <div class="child-area"> <Leftnav :childMes="message"></Leftnav> <button @click="getChild">getChild</button> </div> </div> </template> <script> import Leftnav from '.. /common/LeftNavItem' export default { name: 'blog', data() { return { message: 'father message', } }, components: { Leftnav }, methods: { getChild() { console.log(this.$children[0].childMes); } } } </script> <style scoped> .father-area { background-color: aqua; padding: 10px; } .child-area { background-color: bisque; padding: 10px; } </style>Copy the code

Here the parent component is blog.vue and the child component is leftnavItem. vue, and the parent component calls the child component

<Leftnav :childMes="message"></Leftnav>
Copy the code

Where childMes is a variable to be passed to the child component, that is, the value in the props property of leftnavItem. vue. Multiple variables can be passed

props: ['childMes'.'childMes2'.'childMes3'].Copy the code
  • The variables in props, like the variables in data, get the value directly using this.childmes.
  • :childMes=”message” in “message” is a variable in the parent component’s own data, so if you change the value of message in the parent component, the child component will be updated accordingly.
  • This.$children[0]. ChildMes can be assigned to the value of childMes in the parent component, but cannot be assigned to it.

The child component communicates with the parent component

The parent component passes event methods to the child component, which fires events via $emit and calls back to the parent component. Use $parent to access the parent component's dataCopy the code

Add code to leftNavItem. vue

<template> <div> {{ childMes }} <button @click="toParent">toParent</button> </div> </template> <script> export default {  name: 'LeftNav', props: ['childMes'], methods: { toParent() { this.$emit('mesFunc', 'from children'); console.log(this.$parent); } } } </script> <style lang="scss"> </style>Copy the code

Blog.vue adds code

<template> <div> <div class="father-area"> {{ fatherMes }} </div> <div class="child-area"> <Leftnav :childMes="message" @mesFunc="func"></Leftnav> <button @click="getChild">getChild</button> </div> </div> </template> <script> import Leftnav  from '.. /common/LeftNavItem' export default { name: 'blog', data() { return { message: 'father message', fatherMes: 'Hello World' } }, components: { Leftnav }, methods: { getChild() { console.log(this.$children[0].childMes); }, func(data) { console.log(data); this.fatherMes = data; } } } </script> <style scoped> .father-area { background-color: aqua; padding: 10px; } .child-area { background-color: bisque; padding: 10px; } </style>Copy the code
  • The parent component Blog. Vue is passed

    <Leftnav :childMes="message" @mesFunc="func"></Leftnav>
    Copy the code

    Pass the event method mesFunc to the child component

  • The child component leftnavItem. vue can emit events and pass data through $emit

    this.$emit('mesFunc'.'from children')
    // The first argument: the event passed by the parent component
    // The second argument: the data to be passed to the parent
    Copy the code

State Management (Vuex)

What is Vuex

Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way.Copy the code

The above is the official introduction, the colloquial point will be a bit like global variables, to manage various states. The template definition of Store in Vuex is as follows:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  state: {},actions: {},mutations: {},getters: {},modules: {}})export default store
Copy the code
  • State: Defines the data structure of the application state, where the “state value” is stored
  • Action: Defines the description of the change information triggered by the submission. A common example is to get data from the server and call store.mit () to change the state in the Store after the data is retrieved. You can use Dispatches in components to issue actions
  • Mutations: The only place that allows app status updates
  • Getters: Getters allows the component to get data from the Store
  • Modules: Modules objects allow you to split a single Store into multiple stores while keeping them in a single state tree

Initialize the state

Create folder store under SCR and create file index.js in store

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

const state = {
  currentArticle: {id: '1'.title: 'Study Notes'.tag: 'vue'},   // Current post status, name, tag
  count: 1
}

// Replace Mutation event types with constants
const types = {
  CURRENT_ARTICLE: 'CURRENT_ARTICLE'.COUNT: 'COUNT'
}

constactions = { currentArticle({commit}, obj) { commit(types.CURRENT_ARTICLE, obj); }, countIncrement({commit}, n) { commit(types.COUNT, n); }}const mutations = {
  [types.CURRENT_ARTICLE](state, obj) {
    obj.id == undefined ? false : state.currentArticle.id = obj.id;
    obj.title == undefined ? false : state.currentArticle.title = obj.title;
    obj.tag == undefined ? false : state.currentArticle.tag = obj.tag;
    obj.catalog == undefined ? false : state.currentArticle.catalog = obj.catalog;
  },
  [types.COUNT](state, n = 1) { state.count += n; }}export default new Vuex.Store({
  state,
  actions,
  mutations,
})
Copy the code

Under the ES6 understand

Before moving on, take a look at the new ES6 syntax tutorial

  1. Destruct assignment of an object. Variables must have the same name as attributes to get the correct value

    let { foo, bar } = { foo: "aaa".bar: "bbb" };
    foo // "aaa"
    bar // "bbb"
    
    constactions = { currentArticle({commit}, obj) { commit(types.CURRENT_ARTICLE, obj); }},/ / is equivalent to
    constactions = { currentArticle(context, obj) { context.commit(types.CURRENT_ARTICLE, obj); }},// The first argument passed to currentArticle is a context object with the same methods and properties as the store instance. Or you can get state and getters by context.state and context.getters, just using context.com MIT, so you can{commit} = context commit = context.mitCopy the code
  2. ES6 allows variables to be written directly to objects. In this case, the property name is the variable name, and the property value is the value of the variable

    const foo = 'bar';
    const baz = {foo};
    baz // {foo: "bar"}
    
    / / is equivalent to
    const baz = {foo: foo};
    
    export default new Vuex.Store({
      state,
      actions,
      mutations,
    })
    
    / / is equivalent to
    export default new Vuex.Store({
      state: state,
      actions: actions,
      mutations: mutations
    })
    Copy the code
  3. Object method properties can be abbreviated

    const o = {
      method() {
        return "Hello!"; }};/ / is equivalent to
    
    const o = {
      method: function() {
        return "Hello!"; }};Copy the code
  4. ES6 allows literals to define objects using method two (expressions) as the object’s attribute name, that is, by placing the expression inside square brackets

    let propKey = 'foo';
    
    let obj = {
      [propKey]: true['a' + 'bc'] :123
    };
    Copy the code

    so

    const mutations = {
      [types.CURRENT_ARTICLE](state, obj) {
    
      },
    }
    / / is equivalent to
    const mutations = {
      ['CURRENT_ARTICLE'](state, obj) {
    
      },
    }
    / / is equivalent to
    const mutations = {
      CURRENT_ARTICLE: function(state, obj) {},}Copy the code

Use state in components

To get to the point, we define a currentArticle object, which records the id, title, tags, and catalog of the currentArticle, again using blog. vue and leftnavitem. vue

// Blog.vue<template> <div> <div class="father-area"> id: <input type="text" v-model="currentArticle.id"> title: <input type="text" v-model="currentArticle.title"> tag: <input type="text" v-model="currentArticle.tag"> count: <input type="text" v-model="count"> </div> <div class="child-area"> <Leftnav></Leftnav> </div> </div> </template> <script> import Leftnav from '.. /common/LeftNavItem' import store from '.. /.. /store/demo' export default { name: 'blog', data() { return { message: 'father message' } }, components: { Leftnav }, methods: { }, computed: { currentArticle() { return store.state.currentArticle }, count() { return store.state.count } } } </script> <style scoped> .father-area { background-color: aqua; padding: 10px; } .child-area { background-color: bisque; padding: 10px; } </style>Copy the code

We can introduce stores within each component

import store from '.. /.. /store/index'
Copy the code

It can be seen that when we want to obtain multiple states, it will be repetitive and redundant to declare these states as calculated attributes. The built-in mapState auxiliary function can help us produce calculated attributes. To use helper functions, you need to register the Store instance with the Vue instance, so that the Store instance is injected into all components under the component, and the child components can be accessed through this.$store.

SRC /main.js imports the Store instance and registers the Store option in the vue root instance

import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'
import store from './store/index.js'

Vue.config.productionTip = false

Vue.use(ElementUI)
Vue.prototype.$http = axios

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})
Copy the code

Rewrite the SRC/components/page/Blog. Vue use mapState auxiliary function production status attributes

<template> <div> <div class="father-area"> id: <input type="text" v-model="currentArticle.id"> title: <input type="text" v-model="currentArticle.title"> tag: <input type="text" v-model="currentArticle.tag"> count: <input type="text" v-model="count"> </div> <div class="child-area"> <Leftnav></Leftnav> </div> </div> </template> <script> import Leftnav from '.. /common/LeftNavItem' import { mapState } from 'vuex'; export default { name: 'blog', data() { return { message: 'father message' } }, components: { Leftnav }, methods: { }, computed: mapState(['currentArticle', 'count']) } </script> <style scoped> .father-area { background-color: aqua; padding: 10px; } .child-area { background-color: bisque; padding: 10px; } </yle>Copy the code

MapState can pass in objects as well as arrays

// 1. Only the function returns the state
computed: mapState({
  currentArticle: state= > state.currentArticle,
  count: state= > state.count
})

// 2. Use the alias corresponding state attribute. The value in the object corresponds to state => state.value
// The key value is the alias of the state value. Value is the state value in state. It cannot be shortened to {currentArticle, count}
computed: mapState({
  currentArticle: 'currentArticle'.count: 'count'
})

// 3. Because there may be other computed attributes in computed data, not just mapState, mixing it with other computed attributes requires the extended operator of the object (...). Fetch all traversable properties of the parameter object and copy them to the current object, for example:
let z = { a: 3.b: 4};
letn = { ... z };// Same as n = object.assign ({}, z)
n // ( a: 3, b: 4 )

// the mapState function returns an object, so mix other computed attributes:computed: { otherComputed() { }, ... mapState(['currentArticle'.'count']) // Objects can also be passed in
}
Copy the code

Action

The Action commits mutation rather than directly modifying the statusCopy the code

Distribution of the Action

The Action is triggered by the store.dispatch method to add a button and a method to the blog. vue to increase the count value

<template> <div> <div class="father-area"> id: <input type="text" v-model="currentArticle.id"> title: <input type="text" v-model="currentArticle.title"> tag: <input type="text" v-model="currentArticle.tag"> count: <input type="text" v-model="count"> <button @click="countAdd">+</button> </div> <div class="child-area"> <Leftnav></Leftnav> </div> </div> </template> <script> import Leftnav from '.. /common/LeftNavItem' import { mapState } from 'vuex'; export default { name: 'blog', data() { return { message: 'father message' } }, components: { Leftnav }, methods: { countAdd() { this.$store.dispatch('countIncrement'); } }, computed: mapState(['currentArticle', 'count']) } </script> <style scoped> .father-area { background-color: aqua; padding: 10px; } .child-area { background-color: bisque; padding: 10px; } </style>Copy the code

After clicking the + sign, call countAdd to trigger the Action of countIncrement, and then trigger the mutation of type COUNT to complete the modification of the state. Depending on the definition of the countIncrement method in the action, we can pass in the second argument, this.$store.dispatch(‘countIncrement’, 3).

Helper function mapAction

Action also has a helper function, mapAction, that maps the component’s methods to store.dispatch.

<template> <div> <div class="father-area"> id: <input type="text" v-model="currentArticle.id"> title: <input type="text" v-model="currentArticle.title"> tag: <input type="text" v-model="currentArticle.tag"> count: <input type="text" v-model="count"> <button @click="countAdd">+</button> </div> <div class="child-area"> <Leftnav></Leftnav> </div> </div> </template> <script> import Leftnav from '.. /common/LeftNavItem' import { mapState, mapActions } from 'vuex'; export default { name: 'blog', data() { return { message: 'father message' } }, components: { Leftnav }, methods: { countAdd() { this.countIncrement(2); },... MapActions (['countIncrement']) // Map this.countIncrement to this.$store.dispatch('countIncrement)}, computed: mapState(['currentArticle', 'count']) } </script> <style scoped> .father-area { background-color: aqua; padding: 10px; } .child-area { background-color: bisque; padding: 10px; } </style>Copy the code

Like mapStata, mapActions can also pass in objects using aliases instead of countIncrement

methods: {
  countAdd() {
    this.add(2);
  },
  ...mapActions({
    add: 'countIncrement'})}Copy the code

Personally, I think state and actions in VUEX are difficult to understand, so I will write them down in my notes. Other official documents should be able to understand them, and they are similar to these two usages.

Modular store

For large projects, it is common to split vuEX related code into modulesCopy the code

Create a new file under SRC /store

  • Index. js // Initialize state and export vuex. Store instance
  • Actions. Js // Acitons object
  • Mutation_type. Js // normally quantified mutation type
  • Js // mutation object
// index.js
import Vue from 'vue'
import Vuex from 'vuex'
import actions from './action'
import mutations from './mutation'

Vue.use(Vuex);

const state = {
  currentArticle: {id: '1'.title: 'Study Notes'.tag: 'vue'},
  count: 1
}

export default new Vuex.Store({
  state,
  actions,
  mutations,
})

// actions.js
import * as types from './mutation_type'

export default{ currentArticle({commit}, obj) { commit(types.CURRENT_ARTICLE, obj); }, countIncrement({commit}, n) { commit(types.COUNT, n); }}// mutation_type.js
export const CURRENT_ARTICLE = 'CURRENT_ARTICLE'
export const COUNT = 'COUNT'

// mutation.js
import * as types from './mutation_type'

export default {
  [types.CURRENT_ARTICLE](state, obj) {
    obj.id == undefined ? false : state.currentArticle.id = obj.id;
    obj.title == undefined ? false : state.currentArticle.title = obj.title;
    obj.tag == undefined ? false : state.currentArticle.tag = obj.tag;
    obj.catalog == undefined ? false : state.currentArticle.catalog = obj.catalog;
  },
  [types.COUNT](state, n = 1) { state.count += n; }}Copy the code

Then register the Store instance in main.js

// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index.js'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})
Copy the code