Building vue mobile project from scratch to online

Keywords: Vue Mobile less axios

Let's see a wave of renderings


Initialize project

1. Installed on node.js Using the following command

npm install --g vue-cli

2. Under the directory where the project will be built

Vue init webpack myproject (project directory name)

All the way back here

In the middle, you can select ESLint to check the code style of the project. For the sake of beauty and efficiency, you can start it, use Vue router, and use the two tests in the red box. Don't forget. The next step is to ask which one to use for the install dependency package, which is npm by default. Then you can return and wait for the dependency to be downloaded. If it's slow, you can use it image.

After downloading, you will see the following prompt:

Just follow the steps

Next, type in the browser localhost:8080 , you can enter the world of vue

These are not enough. This is far from a responsive app framework. Let's officially build a mobile project.

First, let's take a look at the project structure of the newly built vue

It can be found that there are two folders in the project, assets and static, which can store static files. Isn't that a conflict? In fact, the static files stored in assets will be processed by webback. Generally, some static resources such as pictures will be placed, while static will not be affected by webback. When it is called, it is also called by absolute path, which is usually used to store some third-party static resource libraries.

This project will be based on the project directory of Vue cli to integrate Vue router, vuex and axios, and can automatically adapt to the size of mobile terminal.

Before you start writing code, let's talk about ESlint warning and error reporting. You can optionally modify the verification rules, Click reference to modify You can also use / * eslint disable * / to selectively ignore the verification

Route (Vue router)

The routing of a project is the foundation of a project. We start with routing. When we first initialize the project, Vue router is introduced into the project. In the above picture, the routing configuration file is placed in src\router. According to my personal habits, I will adjust the directory structure above, as follows:

Create a new page directory to store the main logical page, components to store the public components, and router to manage routes uniformly

Introduce a new page as shown in the figure, and the route can jump through this$ router.push ('/Home')

Route Vue cli is almost encapsulated, but there is nothing to change. Next, let's look at vuex

vuex (state management module)

The official website of the introduction of vuex also gives a detailed introduction. If you don't know much about its function, you can refer to it What is vuex , only how to integrate in the project and briefly introduce its usage

(1) Install vuex

npm install vuex --save

(2) Configure vuex

According to personal development habits, the configuration of vuex in the project is also different, but it's almost the same. There are also big differences. For example, the official website recommends writing asynchronous operations in actions to change the state. However, I prefer to put asynchronous operations such as request data outside the store for operation, and change the state through commit, which will be in the following data request module As mentioned in the package

No more bullshit. Look at the picture below

First, a status folder is created to manage the whole status. In modules, the status of each module is written separately, as follows

 1 /**
 2  * home.js
 3  * State management for home module
 4  */
 5 import * as types from '../mutation-type'  // Methods of introducing definitions
 6 const home = {
 7   state: {
 8     number: 1
 9   },
10   mutations: {
11     [types.SET_NUM](state, num) {   // modify state Available through mapMutations call
12       state.number = num
13     }
14   },
15   actions: {},
16   getters: {            // definition getters,Through mapGetters Extended function call
17     number: state => {
18       return state.number
19     }
20   }
21 }
22 export default home    // output home modular

The mutation type defines some ways to modify the state, as follows

stay index.js Unified output, as follows

 1 import Vue from 'vue'
 2 import Vuex from 'vuex'
 3 import home from './modules/home'
 4 import createLogger from 'vuex/dist/logger'
 6 Vue.use(Vuex)
 7 const debug = true
 9 export default new Vuex.Store({
10   modules: {
11     home
12   },
13   plugins: debug ? [createLogger()] : []   // Open or not vuex Of debug pattern
14 })

A built-in plug-in of vuex is used here, as shown in the figure above. You can view the modification information in the console every time you change the status after opening it, as shown in the figure below

After the index is configured, it is necessary to main.js Register in

Through the above steps, you can use the status in the project home.vue For example, look at the following code

 1 import {mapMutations, mapGetters, mapState} from 'vuex'  // introduce map method
 2 export default {
 3   data () {
 4     return {
 5       num: 0
 6     }
 7   },
 8   methods: {
 9     ...mapMutations({            // call setNum method
10       setNum: 'SET_NUM'
11     }),
12     increase() {
13       this.num++
14       this.setNum(this.num)      // take this.num to change into setNum
15     }
16   },
17   computed: {
18     // ...mapGetters([           // Get state data through getters
19     //   'number'
20     // ]),
21     ...mapState({                // Get state data through state
22       number: state => state.home.number
23     })
24   }

This is the end of the introduction of vuex. Let's continue to look at the data request module (axios)

axios (data request module)

Previously, the vue data request module used vue resource, which is not recommended or discarded by the government. Let's talk about the integration steps of axios and some points to be noted

(1) Install axios and JS cookies

npm install axios --save

(2) Configure axios

Create a new apiconfig folder under the src directory to encapsulate the request and define some global variables about the request. At the same time, create an api folder to declare the request methods of each module, as shown in the following figure

First, let's look at the public encapsulation part of apiconfig; here we will do the following for the request

  • Define some constants such as the status of successful request return, request timeout, etc,
  • Make a public encapsulation of the request,
  • Store and intercept token s,

Look at the code below

 1 /* eslint-disable */
 2 import axios from 'axios'
 4 /**
 5 * Define request constant
 7 */
 8 export const TIME_OUT = 1000;    // Request timeout
 9 export const ERR_OK = true;      // Request successfully returns status, field and background are unified
10 export const baseUrl = process.env.BASE_URL   // IMPORT Global url,Defined in global variable process.env For the convenience of forwarding, the value is empty string
12 // Request timeout
13 axios.defaults.timeout = TIME_OUT
15 // Encapsulation request interception
16 axios.interceptors.request.use(
17     config => {
18         let token = localStorage.getItem('token')   // obtain token
19         config.headers['Content-Type'] = 'application/json;charset=UTF-8'
20         config.headers['Authorization'] = ''
21         if(token != null){                          // If token Not for null,Otherwise token To the backstage
22             config.headers['Authorization'] = token
23         }
24         return config
25     },
26     error => {
27         return Promise.reject(error)
28     }
29 )
30 // Package response interception, judgment token Expired or not
31 axios.interceptors.response.use(
32   response => {
33     let {data} = response
34     if (data.message === 'token failure!') {    // If the error ID returned by the background is token Expired, log in again
35       localStorage.removeItem('token')          // token Expire, remove token
36       // Log in again
37     } else {
38       return Promise.resolve(response)
39     }
40   },
41   error => {
42     return Promise.reject(error)
43   }
44 )
45 // encapsulation post request
46 export function fetch(requestUrl, params = '') {
47   return axios({
48     url: requestUrl,
49     method: 'post',
50     data: {
51       'body': params
52     }
53   })
54 }

The above code takes post request as an example to encapsulate the request in public, and defines some constants for the use of the request. In addition, it intercepts the request and response respectively, so as to facilitate the unified processing of the data when the request or data is returned. The details can be seen in the comments of the code. Next, take login as an example to call the encapsulated request method.

Let's look at the api module. Take home api as an example and look at the code

 1 /**
 2  * Introducing fetch and baseUrl
 3  * @param params
 4  * @returns {*}
 5  */
 6 import {fetch, baseUrl} from 'config/index'
 7 // Login interface
 8 export function loginUserNo(params) {
 9   return fetch(`${baseUrl}/root/login/checkMemberLogin`, params)
10 }

The fetch method and baseUrl are introduced into the file. Why can they be abbreviated as' config/index 'here? It needs to be in' build '/ webpack.base.conf Add the following code in. JS', and the api will be introduced later

After the export login method loginUserNo, you can use this login method in the component, as shown in the following code

 1 import * as homeApi from 'api/home-api'  // introduce api
 2 import { ERR_OK } from 'config/index'    // Import request success status
 3 // Request method
 4 login() {
 5     let params = {
 6         password: '*******',
 7         storeNo: '',
 8         userName: '*********'
 9     }
10     homeApi.loginUserNo(params).then((res) => {
11         let {data} = res
12         if (data.success === ERR_OK) {
13             // Request successful operation, store token
14             localStorage.setItem('token', data.value.token)
15         } else {
16         }
17       }).catch(() => {
18       })
19     }
20 }

You can call the request method by executing the login method after clicking login, but there is another problem

As for data request, a common problem is cross domain. Similarly, clicking on login above will also involve cross domain non request. Fortunately, Vue cli has been configured with a module to solve cross domain problems. We can use config/index.js It is configured with the following addresses to be represented, as shown in the following figure

The cross domain problem is solved by forwarding the api starting with root and pointing the address to the interface address.

So far, the introduction and application of vue family bucket has been basically completed, but so far, this project only has simple routing jump, state storage and data request, and our goal is a mobile application framework. Next, we need to solve the following problems

  • Mobile adaptation
  • Introduction of mobile ui framework
  • Optimization of project organization structure

Let's start with the mobile adaptation

Project adaptation

Because the screen size and proportion of mobile devices are quite different, the adaptation of mobile devices is particularly important. Here we mainly use flexible.js To adapt, about flexible.js I don't know what to say here Here we take the most commonly used size of 750 * 1334 as an example

introduce flexible.js , on main.js Introgression flexible.js File, can flexible.js As a static file, it is imported into the outermost static folder, as shown in the following figure

Using less as the preprocessor of css, install less first

(1) Install less and less loader

npm install less less-loader --save-dev

(2) Configure less

In build/webpack.base.conf.js's module.exports.module.rules

1 {
2     test: /\.less$/,
3     loader: 'style-loader!css-loader!less-loader'
4 },

Then when using in components, you can use less normally by adding lang="less" to the style tag. Here, we introduce some less files of initialization project, create the styles folder under src, and put them into the following files

In the style tag of each component index.less and variable.less

 1 <style scoped lang="less">
 2 @import "~styles/index.less";
 3 @import "~styles/variable.less";
 4 .hello{
 5   h1{
 6     color: red;
 7     .fs(38);     // mixin Li number size function
 8   }
 9 }
10 </style>

And when it says about the pixel style, it's all in mixin.less Under the definition, the adaptation problem for all mobile terminals can be realized.

Mobile page switching and switching animation

Here, the switching animation is taken out separately. As a general requirement of mobile terminal, the transition animation is not required for the first level menu switching, and the transition animation is required for the transition from the first level menu to the second level menu. The following solutions are provided for this requirement.

If you need to use animation, you must use vue transition. If you are not familiar with it, you can see it here The solution to implement animation here is to determine the direction of the route to be executed. The following code defines the route method in the route configuration file

 1 // Need left animation for routing this.$'****')
 2 Router.prototype.togo = function (path) {
 3   this.isleft = true
 4   this.isright = false
 5   this.push(path)
 6 }
 7 // Need the route of the right direction animation this.$router.goRight('****')
 8 Router.prototype.goRight = function (path) {
 9   this.isright = true
10   this.isleft = false
11   this.push(path)
12 }
13 // To return the route of button animation this.$router.goBack(),Return to previous route
14 Router.prototype.goBack = function () {
15   this.isright = true
16   this.isleft = false
17   this.go(-1)
18 }
19 // Click the browser Back button to execute. At this time, route fallback is not required
20 Router.prototype.togoback = function () {
21   this.isright = true
22   this.isleft = false
23 }

When executing route jump above, the App.vue Inside, judge the sliding direction to specify the direction of animation. If you don't need animation, you can use this directly$ router.push ('* * * *'), here is App.vue Animation code processed in

  <div id="app">
    <transition :name="transitionName">
      <router-view class="Router"></router-view>

export default {
  name: 'App',
  data() {
    return {
      transitionName: 'slideleft'
  watch: {
    $route() {   // Monitor route change reassignment
      if (this.$router.isleft) {
        this.transitionName = 'slideleft'
      if (this.$router.isright) {
        this.transitionName = 'slideright'

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
.Router {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  width: 100%;
  height: 100%;
  transition: all .5s ease;
  -webkit-transition: all .5s ease;
  -moz-transition: all .5s ease;
 .slideright-leave-active {
  opacity: 0;
  -webkit-transform: translate(100%, 0);
  transform: translate(100%, 0);
.slideright-enter {
  opacity: 0;
  -webkit-transform: translate(-100%, 0);
  transform: translate(-100%, 0);

Use in components

1 this.$router.goBack()   // return
2 this.$'****')  // Go to details

Another step is to monitor and click the browser Back button, and then main.js Here's the code

1 window.addEventListener('popstate', function(e) {
2   router.togoback()   // router It's already up there import come in
3 }, false)

Mobile UI framework selection

As a mobile project, the above steps have been improved in fact. However, when the project schedule is tight or there is a lack of manpower, the introduction of a mobile UI at this time will be even more powerful. You don't need to encapsulate some UI components by yourself. Here, you can use the mint UI to search for its own advantages. Let's talk about the introduction of mint UI.

(1) Install Mint UI

npm install mint-ui --save

(2) Introducing Mint UI

stay main.js Introducing Mint UI

1 import Mint from 'mint-ui'
2 import 'mint-ui/lib/style.css'  // introduce css
3 Vue.use(Mint)   // Global use

In this way, you can use the mint UI components in the entire vue project.


Some problems in packaging

(1) After packing, click the element on ios and a translucent gray box will pop up. Here you need to add a sentence of css for compatibility - WebKit tap highlight- color:rgba (0,0,0,0); put it in the css of the app

(2) A delay of 300ms to the right of the click event can be used fastclick.js To resolve, refer to the following code

1 npm install fastclick --save
3 // stay main.js introduce
4 import FastClick from 'fastclick'
5 FastClick.attach(document.body)

Packing precautions

If the project is packaged for the mobile browser, it can be packaged directly without changing other things. After the package is uploaded to the server, use nginx for interface forwarding

If you want to further package the packed static files into mobile applications, you need to modify the following config/index.js

In config/prod.env.js New baseUrl

After being packaged as an app, there will be no cross domain problem on the mobile side.

Write at the end

The above project is purely personal built, and is suitable for mobile terminal projects, including browser side, WeChat official account and android, ios application after packaging. There are still some deficiencies, but the basic functions can be used normally. Specific code can be downloaded in my github if necessary. If you think it is useful to you, please give me some advice. Please put forward.

Project address:

The project has added the mock function. For details, see here: vue project configuration Mock.js

Posted by zuhalter223 on Sun, 07 Jun 2020 01:05:45 -0700