How to use Vuex+vue.js to build a single page application _javascript technique

Source: Internet
Author: User
Tags button type

In the recent study of Vue.js, I saw a foreign article about how to use Vue.js and Vuex to build a single page application of simple notes. Feel a lot of harvest, their own examples based on a number of optimization and customization functions, here and you share the learning experience.

In this tutorial we will learn how to use Vuex in our Vue projects by building a note application. We will probably go over what is vuex.js, when to use it in a project, and how to build our Vue application.

Here is a picture of our project:

Project Source: Vuex-notes-app, students who need to download the source directly to view.

Main points of knowledge
The use of Vuex State management mechanism
Vue.js's Base API
Installation and application of VUE-CLI scaffold
The use of Vur-router
ES6 's grammar, here is recommended to see the first tour of Ruan Feng's introductory tutorial

Vuex Overview
before we can wait to start the project, we'd better take a few minutes to understand the core concept of Vuex.

Vuex is a centralized state management architecture designed specifically for vue.js applications. It draws on the design idea of Flux and redux, but simplifies the concept, and uses a specially designed implementation to better exert the vue.js data response mechanism.

State this concept may feel a bit blurry when it first touches, simply by seeing state as a collection of data used in our projects. Vuex then makes a certain difference between the component's native state (component) and the application-level State (application).

Component Local state: This status represents the state that is used only within the component, somewhat similar to the meaning of passing in the Vue component via configuration options.
application Level state: Applies hierarchy status, representing the level of state shared by multiple components at the same time.

Suppose there is a scenario where we have a parent component that contains two subcomponents. The parent component can easily pass data to a subassembly by using the props property.

But the question is, how do our two subassemblies communicate with each other? Or how does a subassembly pass data to his parent component? When our project is very small, neither of these problems is too difficult, because we can communicate with the parent component and the child component through event distributing and listening.

However, as our project grows:

1. It will be difficult to keep track of all events. Which event is distributed by which component and which component should listen for which event?
2, the project logic dispersed in each component, it is easy to lead to logical confusion, not conducive to our project maintenance.
3, the parent component will become more and more serious coupling with the subassembly because it needs to explicitly distribute and listen to some of the child component's events.

This is the problem that Vuex to solve. The four core concepts of VUEX are:

The state tree : Vuex uses a single state tree, with an object that contains all of the application-level state. It now exists as a "unique data source (Ssot)". This also means that each application will contain only one instance of the store. A single state tree allows us to directly locate any particular state fragment, and can easily take a snapshot of the entire current application state during debugging.
getters: used to get Vue component data from the store.
mutators: event handlers are used to drive state changes.
Actions: functions that can be used with components to drive event handlers mutations
How do you temporarily not quite understand this four concepts, do not worry, we will be in the back of the project in a detailed explanation of the actual combat.

The following diagram explains in detail the flow of data in Vuex applications (VUEX Official chart)

Simple explanation:

Vuex stipulates that the state belonging to the application level can only be modified by means of Mutation, and that the events in the Mutation can only be done through the action.

From the left to the start, the component calls the action, at the action level we can interact with the background data, such as getting the initialized data source, or filtering the intermediate data. Then distribute Mutation in the action. Mutation to trigger the change of state, the change of state, will trigger the update of the view.

Attention matters

The data flow is one-way.
Component can invoke the action
The action is used to distribute Mutation
Only mutation can change the state.
The store is responsive and updates are synchronized whenever the state is updated

Environment installation
This application will use Webpack to do modular packaging, processing, and thermal restart. Use of Vue official scaffold vue-cli.

Install VUE-CLI
NPM install-g vue-cli
Note: Node.js >= 4.x, 5.x best

Initialization application

Vue Init webpack vue-notes-app
CD vue-notes-app
npm Install//Installation Dependency pack
npm Run dev/start service

Initializes an application with a project name of Vue-notes-app and chooses to use the Webpack packaging method. At the command line, select the initialization configuration item as prompted. The selection of AirBNB specification is recommended when selecting JSLint check.

Using your favorite editor to open our newly-built project, the structure of the project is probably as follows:

components/folders are used to store our Vue components
The vuex/folder stores things related to the Vuex store (state object,actions,mutators)
The build/file is a webpack package compilation configuration file
The config/folder stores some configuration items, such as the port configuration that our server accesses
dist/The folder did not exist at first and will not be produced until after our project has been build
App.vue root component, all subassemblies will be referenced here
Index.html the entry file for the entire project, will refer to our root component App.vue
The JS logic of the Main.js entry file is injected into the index.html after Webpack is packaged

Functional modules
Add notes, add a note, edit area to display empty notes
Delete notes, after you delete a note, the editing area displays the first item in the current note category
Note list toggle, divided into all notes and collection notes two, after the switch, the editing area displays the first note of the current list
Collect notes and label the currently active notes as favorites

Project Component Partitioning
In this project, we will use a total of four components: the root component App.vue, the Action Bar component Toolbar.vue, the table component Noteslist.vue, the note editing component Editor.vue.

Create Vuex Store
According to the function module we listed above, we create a store.js file under vuex/.

Import Vue from ' Vue ';

Import Vuex from ' Vuex ';

Vue.use (VUEX);

The state that needs to be maintained is "Const" = {notes: [], Activenote: {}, show: '};
 Const MUTATIONS = {//initialization state Init_store (state, data) {state.notes = data.notes, state.show = data.show;
 State.activenote = Data.activenote;
 //New Note new_note (state) {var newnote = {id: +new Date (), title: ', Content: ', favorite:false};
 State.notes.push (Newnote);
 State.activenote = Newnote;
 ///Modify Notes Edit_note (state, note) {state.activenote =;
 Modify the raw data for (var i = 0; i < state.notes.length i++) {if (state.notes[i].id = = note.id) {State.notes[i] = Note;
 Break
 }
 };
 ///Delete notes Delete_note (state) {state.notes. $remove (State.activenote); State.activenote = State.notes[0] | |
 {};
 },//toggle collection and cancellation of notes Toggle_favorite (state) {state.activeNote.favorite =!state.activenote.favorite;
 //Toggle the Display data list type: All or Favorites Set_show_all (state, show) {state.show = Show; Toggle data Display, need to sync update activenote if (show = = = ' FAvorite ') {state.activenote = State.notes.filter (note => note.favorite) [0] | |
 {}; }else{state.activenote = State.notes[0] | |
 {};
 },//Set the currently active notes Set_active_note (state, note) {state.activenote =;

}
};

 Export default New Vuex.store ({state, mutations});

creates a Vuex Actions
under vuex/to establish a action.js that is used for the function of the component.

function Makeaction (type) {return ({dispatch}, ... args) => dispatch (type, ... args);

Const INITNOTE = {ID: +new Date (), title: ' My Notes ', content: ' First note ', favorite:false};

Simulate initialization Data Const INITDATA = {show: ' All ', notes: [Initnote], activenote:initnote};
Export Const Initstore = ({dispatch}) => {dispatch (' Init_store ', initdata);

Update current Activenote object Export Const Updateactivenote = makeaction (' set_active_note ');

Add a Note object export const Newnote = makeaction (' new_note ');
Delete a Note object export const Deletenote = makeaction (' delete_note ');
Export Const Togglefavorite = makeaction (' Toggle_favorite ');

Export Const Editnote = makeaction (' edit_note ');
Update list Show Export const Updateshow = makeaction (' Set_show_all ');

Create Vuex getters a getter.js file under vuex/to get data from the store. To obtain notelist, this will be done according to State.show state of the Data filter export Const Filterednotes = (states) => {if (state.show = = "All") {return State.notes | |
 {}; }else if (state.show = = ' favorite ') {RetuRN State.notes.filter (Note => note.favorite) | |
 {};


}
};

Get list Display status: All or favorite export const show = (state) => {return state.show;};

 Get current activation Note export Const ACTIVENOTE = (state) => {return state.activenote;};

That's all the logic of our Vuex, and after we've set the functionality we need to complete, the next thing we need to do is call the action in the component to implement the corresponding function.

Routing configuration
Here we will use Vue-router to do the routing, referencing the bootstrap style.

Index.html

<! DOCTYPE html>
 
 

All the entry logic we'll be writing in Main.js.

Main.js

Import Vue from ' Vue ';
Import App from './app ';

Import vuerouter from ' Vue-router ';
Import Vueresource from ' Vue-resource ';

Routing module and HTTP module
vue.use (vueresource);
Vue.use (vuerouter);

Const ROUTER = new Vuerouter ();

Router.map ({
 '/index ': {
 component:app
 }
}});

Router.redirect ({
 ' * ': '/index '
});

Router.start (App, ' #app ');

Root Component App.vue

<template>
 <div id= "app" class= "app" >
 <toolbar></toolbar>
 <notes-list> </notes-list>
 <editor></editor>
 </div>
</template>

<style>
 html, #app {
 height:100%;
 }

 body {
 margin:0;
 padding:0;
 border:0;
 height:100%;
 max-height:100%;
 position:relative;
 }
</style>

<script>
 import Toolbar from './components/toolbar ';
 Import noteslist from './components/noteslist ';
 Import Editor from './components/editor ';
 Import store from './vuex/store ';
 Import {Initstore} from './vuex/actions ';

 Export Default {
 components: {
 Toolbar,
 noteslist,
 Editor
 },
 store,
 Vuex: {
 Actions: {
 initstore
 }
 },
 ready () {
 this.initstore (
)}} </script>

Three subcomponents are referenced in the root component: Toolbar.vue, Noteslist.vue, Editor.vue.

Note: We have added a VUEX option in the configuration that exposes the method defined in our action, and we do only one thing in the root component that initializes the mock data, so we call the actions inside the ready phase of the component lifecycle. Initstore to initialize the state in our store.

Toolbar.vue

<template> <div id= "Toolbar" > <i class= "Glyphicon logo ></i> <i @click =" Newnote "class=" Glyphicon glyphicon-plus "> </i> <i @click = "Togglefavorite" class= "Glyphicon Glyphicon-star": class= "{starred:activeNote.favorite}" ></i> <i @click = "Deletenote" class= "Glyphicon glyphicon-remove" ></i> </div> </template > <script> Import {newnote, Deletenote, togglefavorite} from '.
/vuex/actions '; Import {activenote} from ' ...

/vuex/getters '; Export Default {vuex: {getters: {activenote}, actions: {newnote, Deletenote, Togglefavorite}}} &LT;/SCRI
 pt> <style lang= "Scss" scoped> #toolbar {float:left;
 width:80px;
 height:100%;
 Background-color: #30414D;
 Color: #767676;

 padding:35px 25px 25px 25px;
 . starred {color: #F7AE4F;
 } i{font-size:30px;
 margin-bottom:35px;
 Cursor:pointer;
 opacity:0.8; Transition:opaciTy 0.5s ease;
 &:hover{opacity:1;

 }} </style>

Here we use a case of vuex that we need to know whether the current active note is a collection category, and if so, how do we know if we need to highlight the Favorites button? It is through the vuex inside the getters to get the currently active note object, to determine whether its favorite is true.

Always keep in mind a concept, the data in the Vuex is one-way, can only be obtained from the store, and our example of the activenote is always maintained in the store.js, this way can be shared with other components

The state that needs to be maintained is "Const" = {notes: [], Activenote: {}, show: '}; Noteslist.vue <template> <div id= "notes-list" > <div id= "list-header" >  

Note List component, with three main actions

Render Notes
Toggle Render Notes
Click on the list title to toggle Activenote

We get a list of notes through the Filterednotes method in getters

To obtain notelist, this will be done according to State.show state of the data filter
Export Const Filterednotes = (states) => {
 if (state.show = = ' All ') {
   return State.notes | | {};
 } else if (state.show = = ' favorite ') {return
 state.notes.filter (note => note.favorite) | | {};
 }
};

As you can see, the list we get is dependent on the state of the state.show. And our switching list operation happens to call the actions inside the method to update the state.show, so that the dynamic refresh of the data list, and our operation of the tree is by invoking the actions of the method to achieve.

Let's see, when we switch the list, we also need to update activenote dynamically. Look at what we did in the Store.js:

Toggle Display data List type: All or Favorites
Set_show_all (state, show) {
 state.show = Show;
 Toggle data Display, need to sync update activenote
 if (show = = ' favorite ') {
 state.activenote = state.notes.filter (Note => Note.favorite) [0] | | {};
 } else{
 state.activenote = state.notes[0] | | {};
 }
}

What triggers these operations is that we bind our custom functions to two buttons, and then filter and update the data by passing in different parameters to the function and then invoking the actions inside the action.

Editor.vue

<template>
 <div id= "Note-editor" >
 <div class= "Form-group" >
 <input type= "text" Name= "title"
 class= "title Form-control"
 placeholder= "Please enter the title"
 @input = "Updatenote"
 v-model= " Currentnote.title ">
 <textarea
 v-model=" currentnote.content "name=" content "
 class=" Form-control "row=" 3 "placeholder=" Please enter the body "
 @input =" Updatenote "></textarea>
 </div>
 </div>
</template>

<script>
 Import {editnote} from '. /vuex/actions ';
 Import {activenote} from ' ... /vuex/getters ';

 Export Default {
 Vuex: {
 getters: {
 activenote
 },
 actions: {
 editnote
 }}
 ,
 computed: {
 //an object obtained by calculating the property, this way we can happily use V-model
 currentnote:activenote
 },
 methods: {
 Why did you do that? Because the value
 updatenote () {
 this.editnote (this.currentnote) in
 the state is not
allowed to be modified directly at the template level in strict mode; </script>

In the Editor.vue component, we need to be able to update the current Activenote component in real time and the contents of the corresponding note objects in the list that we are modifying.

As we mentioned earlier, it is not allowed to directly modify the state values of the store.js in the assembly, so here we assign a value to an object in the store with a computed attribute, and then in the custom Updatenotes () method, call the Action, passing in the Currentnote object at the same time.

In the store.js, we do this, find the corresponding ID of the object, reassign, because the previous mentioned, our data is responsive, where the changes, the corresponding view will also refresh changes, so that the real-time editing, real-time rendering function.

Modify Notes
Edit_note (state, note) {
 state.activenote =;
 Modify raw data for
 (var i = 0; i < state.notes.length i++) {
 if (state.notes[i].id = = note.id) {
 state.notes[i] = Note;
 Break;}}
 ;

Q&a

In this project, we did not introduce the Vue-resource plug-in, only to simulate the part of the data, interested students can try their own.

Because our example is relatively simple, does not involve the very deep thing, the deeper research need everybody to spend more time to practice.

Finally, again, in the action, we can actually do more, for example, according to the ID of the dynamic asynchronous acquisition of notes, and so on, these interested students can try their own, a little rich this example.

Original address: https://coligo.io/learn-vuex-by-building-notes-app/

This article has been organized into the "Vue.js front-end component Learning course", welcome to learn to read.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.