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
-
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
-
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
-
Object method properties can be abbreviated
const o = { method() { return "Hello!"; }};/ / is equivalent to const o = { method: function() { return "Hello!"; }};Copy the code
-
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