Best practices for building a single-page application with vue2.0
Preface
We will choose to use vue-cli, vue-router, vue-resource, and vuex libraries around the vue.
1. Use vue-cli to create a project
2. Use vue-router to implement single-page Routing
3. Use vuex to manage our data streams
4. Use vue-resource to request our node Server
5. Use the. vue file for componentized Development
PS: node v6.2.2 npm v3.9.5 vue v2.1.0 vue-router v2.0.3 vuex v2.0.0
In the end, we will build a small demo.
Install
1. We will use webpack to pack, pre-process, and hot load our modules. If you are not familiar with webpack, it can help us pack multiple js files into one entry file and load them as needed. This means that we don't have to worry about using too many components, resulting in too many HTTP requests, which is very beneficial to the product experience. But we don't just use webpack for this purpose. We need to use webpack for compilation. vue file. If no loader is used for conversion. the style, js, and html in the vue file cannot be identified by the browser.
2. module hot loading is a very powerful feature of webpack and will bring great convenience to our single-page applications.
Generally, when we modify the code to refresh the page, all the states in the application will be gone. This is very painful for developing a single-page application because the process needs to be re-run. If a module is hot loaded, When you modify the code, your code will be directly modified and the page will not be refreshed, so the status will be retained.
3. Vue also provides CSS Preprocessing for us, so we can choose to write LESS or SASS in The. vue file to replace native CSS.
4. We used to use npm to download a bunch of dependencies, but now we can choose Vue-cli. This is a great innovation in the vue ecosystem. This means that we don't need to build our project manually, and it can be generated for us quickly.
First, install vue-cli. (Make Sure You Have node and npm)
Npm I-g vue-cli
Create a webpack project and download the dependencies.
Vue init webpack vue-tutorial
Cd vue-tutorial
Npm I
Then run our application in Hot load using npm run dev.
This line of command indicates that it will find the scripts object of package. json and execute node bulid/dev-server.js. If Webpack is configured in this file, it will compile the project file and run the server. We can view our application in localhost: 8080.
After these libraries are ready, we need to download three libraries for our routes, XHR requests, and data management. We can find them on the official vue website. In addition, we use bootstrap as my UI library.
Npm I vue-resource vue-router vuex bootstrap -- save
Initialization (main. js)
View our application files. We can find App. vue and main. js under the src directory. Main. js will serve as the entry file of our application, and App. vue will serve as the initialization component of our application. Let's first Improve main. js.
// Src/main. jsimport Vue from 'vue' import VueRouter from 'vue-router 'import VueResource from 'vue-resource' import App from '. /App 'import Home from '. /components/Home 'import' bootstrap/dist/css/bootstrap.css 'vue. use (VueRouter) Vue. use (VueResource) const routes = [{path: '/', component: Home}, {path: '/home', component: home}]; const router = new VueRouter ({routes});/* eslint-disable no-new * // instantiate our Vuevar app = new Vue ({el: '# app ', router ,... app ,});
This is different from 1.0.
1. Note that the vue-router route parameters are changed from objects to arrays. In addition, the el parameter for vue instantiation cannot be set to html or body, because the specified tag will be replaced in vue2.
2. We must specify the rendering components when instantiating vue. In the past, we used routing to specify components such as router. start (App, '# app'), which is not required in vue2.
We can find that we use two components in main. js: App. vue and Home. vue. Let's implement them later.
While our index.html only needs to retain <div id = "app"> </div>, our Vue sets el during instantiation: '# app' will replace this tag for the content of our app component.
//index.html<div id="app"></div>
The initialization is over. Let's start creating components.
Create homepage Components
First, we will write a top navigation for our application in App. vue.
// Src/App. vue <template> <div id = "wrapper"> <nav class = "navbar-default"> <div class = "container"> <a class = "navbar-brand" href = "#" rel = "external nofollow"> <I class = "glyphicon-time"> </I> scheduler </a> <ul class = "nav navbar -nav "> <li> <router-link to ="/home "> homepage </router-link> </li> <router-link to = "/ time-entries "> scheduler list </router-link> </li> </ul> </div> </nav> <div class =" container "> <div class = "col-sm-3"> </div> <div class = "col-sm-9"> <router-view> </div> </template>
In addition to our navbar, we also need a. container to store the information we need to display.
In addition, we need to place a router-view label here. The vue-router switch is displayed through this label.
There is a difference from 1.0 here.
Previously, we can directly write the tag and then write the v-link attribute for Route jump. In vue2, we can change it to write the <router-link> tag and then write the corresponding attribute (to) for redirect.
Next, we need to create a Home. vue as our Homepage
// Src/components/Home. vue <template> <div class = "jumbotron">
If nothing happens, you can see the following results:
Create sidebar Components
At present, there is a blank area on the left of our homepage. We need it to put a sidebar to count the total time of all the plans.
// src/App.vue //... <div class="container"> <div class="col-sm-3"> <sidebar></sidebar> </div> <div class="col-sm-9"> <router-view></router-view> </div> </div> //...
<script> import Sidebar from './components/Sidebar.vue' export default { components: { 'sidebar': Sidebar }, }</script>
In Sidebar. vue, we need to get the total time through store. Our total time is shared data.
// Src/components/Sidebar. vue <template> <div class = "panel-default"> <div class = "panel-heading">
Create a scheduler list component
Then we need to create our time tracking list.
// Src/components/TimeEntries. vue <template> <div> // 'v-if' is a command of vue // '$ route. path 'is the path of the current route object and will be parsed as an absolute path when/' $ route. path! = '/Time-entries/log-time'' is displayed as 'true', 'false', or not. // To route jump address <router-link v-if = "$ route. path! = '/Time-entries/log-time' "to ="/time-entries/log-time "class =" btn-primary "> Create </router-link> <div v-if = "$ route. path = '/time-entries/log-time' ">
The template explanation is written together. Let's look at our script.
// Src/components/TimeEntries. vue <script> export default {name: 'timeentries', computed: {plans () {// retrieve data from store return this. $ store. state. list }}, methods: {deletePlan (idx) {// method described here later // minus the total time this. $ store. dispatch ('dectotaltime', this. plans [idx]. totalTime) // Delete this plan. $ store. dispatch ('deleteplan', idx) }}</script>
Don't forget to write the required styles for our components.
// src/components/TimeEntries.vue<style> .avatar { height: 75px; margin: 0 auto; margin-top: 10px; margin-bottom: 10px; } .user-details { background-color: #f5f5f5; border-right: 1px solid #ddd; margin: -10px 0; } .time-block { padding: 10px; } .comment-section { padding: 20px; }</style>
Since our data is shared, we need to store the data in the store.
Create a directory named store under src
Create 4 js files under store: actions. js, index. js, mutation-types.js, mutations. js
By reading the name, you will know what these four functions are for. We recommend that you read more vuex documents and learn more about them.
// Src/store/index. jsimport Vue from 'vue' import Vuex from 'vuex' vue. use (Vuex); // first write a false data const state = {totalTime: 0, list: [{name: 'erzhe ', avatar: 'https: // else ', date: '2017-12-25 ', totalTime: '6', comment: 'August 2016 is perfect. It takes 6 hours to spend Christmas with your girlfriend'}]}; export default new Vuex. store ({state ,})
The page and store are added and configured in the js file of our portal.
// src/main.jsimport store from './store'import TimeEntries from './components/TimeEntries.vue'//...const routes = [{ path : '/', component : Home},{ path : '/home', component : Home},{ path : '/time-entries', component : TimeEntries,}];var app = new Vue({ el: '#app', router, store, ...App,});
You can see this page under the/time-entries route.
Through vue-Devtools, we can find that our store has been constructed and data is successfully obtained from the store.
Create task Components
This is relatively simple. Let's give the code directly.
// Src/components/LogTime. vue <template> <div class = "form-horizontal"> <div class = "form-group"> <div class = "col-sm-6"> <label> date </label> <input type = "date" class = "form-control" v-model = "date" placeholder = "Date"/> </div> <div class = "col-sm-6"> <label> time </label> <input type = "number" class = "form-control" v-model = "totalTime" placeholder = "Hours"/> </div> </div> <div class = "form-group"> <div class = "col-sm-12"> <label> remarks </label> <input type = "text" class =" form-control "v-model =" comment "placeholder =" Comment "/> </div> <button class =" btn-primary "@ click =" save () "> Save </button> <router-link to ="/time-entries "class =" btn-danger "> cancel </router-link>
This component is just three inputs, and then there are two buttons. Save them and push the data into our store list.
LogTime is a sub-route of our TimeEntries component, so we still need to configure our route, and use webpack to load it lazily, reducing the traffic loaded on our first screen
// Src/main. js //... const routes = [{path: '/', component: Home}, {path: '/home', component: home}, {path:'/time-entries ', component: TimeEntries, children: [{path: 'Log-time', // lazy loading component: resolve => require (['. /components/LogTime. vue '], resolve),}]; //...
Vuex Section
In vue2.0, in addition to Event-based communication, we can use Event Bus in small projects. It is best to use vuex in other projects. In this article, we use Vuex for data communication.
I believe you have just seen a lot of code similar to this. $ store. dispatch ('saveplan', plan.
Think carefully, we need two global data, one for the total time of all the plans, and the other is an array of the plan list.
Src/store/index. js does not have much to introduce. In fact, it is to pass in our state, mutations, actions to initialize our Store. If necessary, we may need to create our getter in this example.
Then let's look at the mutation-types.js, since we want to clearly understand the data, it should have what kind of operation to look up, of course, this also depends on personal taste
// Src/store/mutation-types.js // increase the total time or decrease the total time export const ADD_TOTAL_TIME = 'add _ TOTAL_TIME '; export const DEC_TOTAL_TIME = 'dec _ TOTAL_TIME '; // add and DELETE a PLAN. export const SAVE_PLAN = 'Save _ plan'; export const DELETE_PLAN = 'delete _ plan'; // src/store/mutations. jsimport * as types from '. /mutation-types 'export default {// increase the total time [types. ADD_TOTAL_TIME] (state, time) {state. totalTime = state. totalTime + time}, // reduce the total time [types. DEC_TOTAL_TIME] (state, time) {state. totalTime = state. totalTime-time}, // Add Plan [types. SAVE_PLAN] (state, plan) {// set the default value. In the future, we can log on and directly read the nickname and avatar const avatar = 'https: // reset state. list. push (Object. assign ({name: 'erzhe', avatar: avatar}, plan)}, // delete a plan [types. DELETE_PLAN] (state, idx) {state. list. splice (idx, 1 );}};
Finally, let's look at our actions.
// src/store/actions.jsimport * as types from './mutation-types'export default { addTotalTime({ commit }, time) { commit(types.ADD_TOTAL_TIME, time) }, decTotalTime({ commit }, time) { commit(types.DEC_TOTAL_TIME, time) }, savePlan({ commit }, plan) { commit(types.SAVE_PLAN, plan); }, deletePlan({ commit }, plan) { commit(types.DELETE_PLAN, plan) }};
Our actions is actually used to trigger events and input parameters.
After these three files are added, our store is complete and our code is updated.
// Src/store/index. complete js Code import Vue from 'vue 'import Vuex from 'vuex' import mutations from '. /mutations 'import actions from '. /actions 'vue. use (Vuex); const state = {totalTime: 0, list: []}; export default new Vuex. store ({state, mutations, actions })
This. $ store. dispatch ('saveplan', plan) calls actions when such a method is executed. in js, The savePlan method triggers types in mutations. SAVE_PLAN last modified data view update
PS: in this case, mutations are all connected with uppercase underscores, while actions is mapped to lower case hump.
Personally, this is actually a publishing and subscription model.
Mutation-types records all our event names
Mutations register our various data change methods
Actions can write asynchronous logic or some logic, and then commit
Our events
If there is a getter, we can place some data that needs to be processed and returned here, without business operations.
Finally, don't forget to use our store in our main. js.
// src/store/main.jsimport store from './store'// ...var app = new Vue({ el: '#app', router, store, ...App,});
Start to experience your own task scheduler!
Last
Through this article, we can learn many vue features.
1. Understand vue-cli scaffolding
2. I have some preliminary knowledge about webpack.
3. How to Use. vue for pleasant Development
4. Use vuex for component communication
5. Application of routing (vro)
6. Use vue-devtools to observe our data
Personal Website: http://www.meckodo.com
Github: https://github.com/MeCKodo/vu...
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.