vue comprehensive notes

Posted by bzenker on Mon, 28 Feb 2022 03:49:21 +0100

note

Scaffold file structure

├── node_modules 
├── public
│   ├── favicon.ico: Tab Icon
│   └── index.html: Main page
├── src
│   ├── assets: Storing static resources
│   │   └── logo.png
│   │── component: Store components
│   │   └── HelloWorld.vue
│   │── App.vue: Summarize all components
│   │── main.js: Entry file
├── .gitignore: git Configuration ignored by versioning
├── babel.config.js: babel Configuration file for
├── package.json: App package profile 
├── README.md: Application description file
├── package-lock.json: Package version control file

About different versions of Vue

  1. vue.js and Vue runtime. xxx. JS difference:
    1. vue.js is the full version of Vue, including: core functions + template parser.
    2. vue.runtime.xxx.js is the running version of Vue, which only contains: core functions; There is no template parser.
  2. Because Vue runtime. xxx. JS has no template parser, so you can't use the configuration item template. You need to use the createElement function received by the render function to specify the specific content.

vue.config.js configuration file

  1. Use Vue inspect > output JS can view the default configuration of Vue scaffold.
  2. Use Vue config. JS can customize the scaffold. For details, see: https://cli.vuejs.org/zh

ref attribute

  1. Used to register reference information (id substitutes) for elements or subcomponents
  2. The application obtains the real DOM element on the html tag, and the application on the component tag is the component instance object (vc)
  3. Usage:
    1. Marking: < H1 ref = "XXX" ></ H1 > or < school ref = "XXX" > < / School >
    2. Get: this$ refs. xxx

props configuration item

  1. Function: let the component receive the data from the outside

  2. Transfer data: < demo name = "XXX" / >

  3. Receive data:

    1. The first method (receive only): props:['name ']

    2. The second method (restriction type): props:{name:String}

    3. The third method (restriction type, restriction necessity, specifying default value):

      props:{
      	name:{
      	type:String, //type
      	required:true, //necessity
      	default:'Lao Wang' //Default value
      	}
      }
      

    Note: props is read-only. Vue bottom layer will monitor your modification of props. If it is modified, it will issue a warning. If the business requirements really need to be modified, please copy the contents of props into data, and then modify the data in data.

Mixin (mixed)

  1. Function: the configuration shared by multiple components can be extracted into a mixed object

  2. Usage:

    Step 1: define mixing:

    {
        data(){....},
        methods:{....}
        ....
    }
    

    Step 2: use blending:

    Global blending: Vue mixin(xxx)
    Local mixing: mixins:['xxx ']

plug-in unit

  1. Features: for enhancing Vue

  2. Essence: an object containing the install method. The first parameter of install is Vue, and the second parameter is the data passed by the plug-in user.

  3. Define plug-ins:

    object.install = function (Vue, options) {
        // 1. Add global filter
        Vue.filter(....)
    
        // 2. Add global instruction
        Vue.directive(....)
    
        // 3. Configure global mixing (integration)
        Vue.mixin(....)
    
        // 4. Add instance method
        Vue.prototype.$myMethod = function () {...}
        Vue.prototype.$myProperty = xxxx
    }
    
  4. Using plug-in: Vue use()

scoped style

  1. Function: make the style take effect locally and prevent conflicts.
  2. Writing method: < style scoped >

Summarize the TodoList case

  1. Componentized coding process:

    ​ (1). Split static components: components should be split according to function points, and their names should not conflict with html elements.

    ​ (2). Realize dynamic components: consider the storage location of data, whether the data is used by one component or some components:

    ​ 1). A component is in use: just put it on the component itself.

    ​ 2). Some components are in use: on their common parent component (state promotion).

    ​ (3). Implement interaction: start with binding events.

  2. props applies to:

    ​ (1). Parent component = = > child component communication

    ​ (2). Child component = = > parent component communication (the parent is required to give the child a function first)

  3. When using v-model, keep in mind that the value bound to v-model cannot be the value passed by props, because props cannot be modified!

  4. If the value passed by props is the value of the object type, Vue will not report an error when modifying the properties in the object, but it is not recommended.

webStorage

  1. The storage content size generally supports about 5MB (different browsers may be different)

  2. Browser side through window Sessionstorage and window Use the localstorage attribute to implement the local storage mechanism.

  3. Related API:

    1. xxxxxStorage.setItem('key', 'value');
      This method accepts a key and value as parameters, and will add the key value pair to the storage. If the key name exists, its corresponding value will be updated.

    2. xxxxxStorage.getItem('person');

      This method takes a key name as a parameter and returns the value corresponding to the key name.

    3. xxxxxStorage.removeItem('key');

      This method takes a key name as a parameter and deletes the key name from the storage.

    4. xxxxxStorage.clear()

      This method will empty all data in the storage.

  4. remarks:

    1. The content stored in SessionStorage disappears as the browser window closes.
    2. The content stored in LocalStorage needs to be cleared manually before it disappears.
    3. xxxxxStorage.getItem(xxx) if the value corresponding to XXX cannot be obtained, the return value of getItem is null.
    4. JSON. The result of parse (null) is still null.

Custom events for components

  1. A way of communication between components, applicable to: child component = = = > parent component

  2. Usage scenario: A is the parent component and B is the child component. If B wants to transfer data to a, it needs to bind a custom event to B in a (the callback of the event is in a).

  3. Bind custom events:

    1. The first method is in the parent component: < demo @ atguigu = "test" / > or < demo v-on: atguigu = "test" / >

    2. In the second way, in the parent component:

      <Demo ref="demo"/>
      ......
      mounted(){
         this.$refs.xxx.$on('atguigu',this.test)
      }
      
    3. If you want a custom event to be triggered only once, you can use the once modifier or the $once method.

  4. Trigger custom event: this$ Emit ('atguigu ', data)

  5. Unbind the custom event this$ off('atguigu')

  6. You can also bind native DOM events on components, and you need to use the native modifier.

  7. Note: through this$ refs. xxx.$ On ('atguigu ', callback) when Binding custom events, the callback is either configured in methods or used as an arrow function, otherwise there will be problems with this pointing!

Global event bus

  1. A way of communication between components, which is suitable for communication between any components.

  2. To install the global event bus:

    new Vue({
    	......
    	beforeCreate() {
    		Vue.prototype.$bus = this //Install the global event bus, $bus is the vm of the current application
    	},
        ......
    }) 
    
  3. Using the event bus:

    1. Receive data: if component a wants to receive data, bind a custom event to $bus in component A, and the callback of the event remains in component a itself.

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.$bus.$on('xxxx',this.demo)
      }
      
    2. Provide data: this$ bus.$ Emit ('xxxx ', data)

  4. It is better to use $off in the beforeDestroy hook to unbind the events used by the current component.

Message subscription and Publication (pubsub)

  1. A way of communication between components, which is suitable for communication between any components.

  2. Use steps:

    1. Install pubsub: NPM I pubsub JS

    2. Import: import PubSub from 'PubSub JS'

    3. Receive data: if component a wants to receive data, it subscribes to messages in component A, and the subscribed callback remains in component a itself.

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.pid = pubsub.subscribe('xxx',this.demo) //Subscribe to messages
      }
      
    4. Data provided: PubSub Publish ('xxx ', data)

    5. It is best to use PubSub. In the beforeDestroy hook Unsubscribe (PID) to unsubscribe.

nextTick

  1. Syntax: this$ Nexttick (callback function)
  2. Function: execute the specified callback after the next DOM update.
  3. When to use: when you need to perform some operations based on the updated new DOM after changing the data, it should be executed in the callback function specified by nextTick.

Vue encapsulated transition and animation

  1. Function: when inserting, updating or removing DOM elements, add style class names to the elements when appropriate.

  2. Illustration:

  3. Writing method:

    1. Ready style:

      • Element entry style:
        1. v-enter: the starting point of entry
        2. v-enter-active: in the process of entering
        3. v-enter-to: end of entry
      • Style of element leaving:
        1. v-leave: the starting point of departure
        2. v-leave-active: in the process of leaving
        3. v-leave-to: end of departure
    2. Use < transition > to wrap the elements to be excessive and configure the name attribute. Note that if the appear ance attribute is configured, it means that the animation is turned on when the real dom is mounted at the beginning:

      <transition name="hello" appear>
      	<h1 v-show="isShow">How do you do!</h1>
      </transition>
      
    3. Note: if multiple elements need to be excessive, you need to use: < transition group >, and each element must specify a key value.

vue scaffold configuration agent

Method 1

In Vue config. JS to add the following configuration:

devServer:{
  proxy:"http://localhost:5000"
}

explain:

  1. Advantages: simple configuration. When requesting resources, it can be sent directly to the front end (8080).
  2. Disadvantages: multiple agents cannot be configured, and it is not possible to flexibly control whether requests go through agents.
  3. Working mode: if the agent is configured according to the above, when a resource that does not exist in the front end is requested, the request will be forwarded to the server (the front-end resource is matched first)

Method 2

Write Vue config. JS configure specific proxy rules:

module.exports = {
	devServer: {
      proxy: {
      '/api1': {// Match all request paths starting with '/ api1'
        target: 'http://localhost:5000 ', / / the basic path of the proxy target
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}
      },
      '/api2': {// Match all request paths starting with '/ api2'
        target: 'http://localhost:5001 ', / / the basic path of the proxy target
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin When set to true, the host in the request header received by the server is: localhost:5000
   changeOrigin When set to false, the host in the request header received by the server is: localhost:8080
   changeOrigin The default value is true
*/

explain:

  1. Advantages: multiple agents can be configured, and it can flexibly control whether requests go through agents.
  2. Disadvantages: the configuration is slightly cumbersome, and the resource request must be prefixed.

slot

  1. Function: enables the parent component to insert html structure into the specified location of the child component. It is also a way of communication between components. It is applicable to parent component = = > child component.

  2. Category: default slot, named slot, scope slot

  3. Usage:

    1. Default slot:

      In parent component:
              <Category>
                 <div>html Structure 1</div>
              </Category>
      In subcomponents:
              <template>
                  <div>
                     <!-- Define slot -->
                     <slot>Slot default content...</slot>
                  </div>
              </template>
      
    2. Named slot:

      In parent component:
              <Category>
                  <template slot="center">
                    <div>html Structure 1</div>
                  </template>
      
                  <template v-slot:footer>
                     <div>html Structure 2</div>
                  </template>
              </Category>
      In subcomponents:
              <template>
                  <div>
                     <!-- Define slot -->
                     <slot name="center">Slot default content...</slot>
                     <slot name="footer">Slot default content...</slot>
                  </div>
              </template>
      
    3. Scope slot:

      1. Understanding: the data is in the component itself, but the user of the component needs to decide according to the structure of data generation. (the games data is in the Category component, but the structure traversed by the data is determined by the App component)

      2. Specific code:

        In parent component:
        		<Category>
        			<template scope="scopeData">
        				<!-- Generated is ul list -->
        				<ul>
        					<li v-for="g in scopeData.games" :key="g">{{g}}</li>
        				</ul>
        			</template>
        		</Category>
        
        		<Category>
        			<template slot-scope="scopeData">
        				<!-- Generated is h4 title -->
        				<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
        			</template>
        		</Category>
        In subcomponents:
                <template>
                    <div>
                        <slot :games="games"></slot>
                    </div>
                </template>
        		
                <script>
                    export default {
                        name:'Category',
                        props:['title'],
                        //The data is in the subcomponent itself
                        data() {
                            return {
                                games:['Red Alert','Cross Fire','Audition','Super Marie']
                            }
                        },
                    }
                </script>
        

Vuex

1. Concept

A Vue plug-in that implements centralized state (data) management in Vue. It centrally manages (reads / writes) the shared state of multiple components in Vue applications. It is also a way of communication between components, and is suitable for communication between any components.

2. When to use?

When multiple components need to share data

3. Build vuex environment

  1. Create file: Src / store / index js

    //Introduce Vue core library
    import Vue from 'vue'
    //Introduce Vuex
    import Vuex from 'vuex'
    //Apply Vuex plug-ins
    Vue.use(Vuex)
    
    //Prepare the actions object -- respond to the user's actions in the component
    const actions = {}
    //Prepare the changes object -- modify the data in the state
    const mutations = {}
    //Prepare the state object -- save the specific data
    const state = {}
    
    //Create and expose store s
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state
    })
    
  2. In main When creating vm in JS, pass in the store configuration item

    ......
    //Introducing store
    import store from './store'
    ......
    
    //Create vm
    new Vue({
    	el:'#app',
    	render: h => h(App),
    	store
    })
    

4. Basic use

  1. Initialize data, configure actions, configure changes, and operate the file store js

    //Introduce Vue core library
    import Vue from 'vue'
    //Introduce Vuex
    import Vuex from 'vuex'
    //Reference Vuex
    Vue.use(Vuex)
    
    const actions = {
        //Action added in response component
    	jia(context,value){
    		// console. Log ('jia in actions is called ', miniStore,value)
    		context.commit('JIA',value)
    	},
    }
    
    const mutations = {
        //Executive plus
    	JIA(state,value){
    		// console. Log ('JIA in changes is called ', state,value)
    		state.sum += value
    	}
    }
    
    //Initialization data
    const state = {
       sum:0
    }
    
    //Create and expose store s
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state,
    })
    
  2. Read data from vuex in component: $store state. sum

  3. Modify data in vuex in component: $store Dispatch ('method name in action ', data) or $store Commit ('method name in changes', data)

    Note: if there is no network request or other business logic, actions can also be crossed in the component, that is, commit can be written directly without writing dispatch

5. Use of Getters

  1. Concept: when the data in state needs to be processed before use, you can use getters processing.

  2. In the store Add getters configuration in JS

    ......
    
    const getters = {
        bigSum(state){
            return state.sum * 10
        }
    }
    
    //Create and expose store s
    export default new Vuex.Store({
        ......
        getters
    })
    
  3. Read data from component: $store getters. bigSum

6. Use of four map methods

  1. mapState method: it is used to help us map the data in state into calculated attributes

    computed: {
        //Generate calculation attributes with mapState: sum, school, subject (object writing method)
         ...mapState({sum:'sum',school:'school',subject:'subject'}),
             
        //Generate calculation attributes with mapState: sum, school, subject (array writing method)
        ...mapState(['sum','school','subject']),
    },
    
  2. mapGetters method: used to help us map the data in getters into calculated attributes

    computed: {
        //Generate calculation attribute with mapGetters: bigSum (object writing method)
        ...mapGetters({bigSum:'bigSum'}),
    
        //Generate calculation attribute with mapGetters: bigSum (array writing method)
        ...mapGetters(['bigSum'])
    },
    
  3. mapMutations method: a method used to help us generate a conversation with mutations, that is, $store Function of commit (xxx)

    methods:{
        //Generated by mapActions: increment and decrement (object form)
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),
        
        //Generated by mapMutations: JIA, JIAN (object form)
        ...mapMutations(['JIA','JIAN']),
    }
    

Note: when mapActions and mapMutations are used, if parameters need to be passed: pass the parameters when binding events in the template, otherwise the parameters are event objects.

7. Modularity + namespace

  1. Purpose: to better maintain the code and make the classification of multiple data more clear.

  2. Modify store js

    const countAbout = {
      namespaced:true,//Open namespace
      state:{x:1},
      mutations: { ... },
      actions: { ... },
      getters: {
        bigSum(state){
           return state.sum * 10
        }
      }
    }
    
    const personAbout = {
      namespaced:true,//Open namespace
      state:{ ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        countAbout,
        personAbout
      }
    })
    
  3. After the namespace is opened, read the state data from the component:

    //Method 1: read directly by yourself
    this.$store.state.personAbout.list
    //Method 2: read with mapState:
    ...mapState('countAbout',['sum','school','subject']),
    
  4. After the namespace is opened, the getters data is read from the component:

    //Method 1: read directly by yourself
    this.$store.getters['personAbout/firstPersonName']
    //Method 2: read with mapGetters:
    ...mapGetters('countAbout',['bigSum'])
    
  5. After namespace is opened, dispatch is invoked in the component.

    //Method 1: directly dispatch yourself
    this.$store.dispatch('personAbout/addPersonWang',person)
    //Mode 2: with the help of action maps:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. After namespace is opened, commit is invoked in the component.

    //Method 1: commit yourself directly
    this.$store.commit('personAbout/ADD_PERSON',person)
    //Method 2: with mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    

route

  1. Understanding: a route is a set of key - value s. Multiple routes need to be managed by a router.
  2. Front end Routing: key is the path and value is the component.

1. Basic use

  1. Install Vue router, command: NPM I Vue router

  2. Application plug-in: Vue use(VueRouter)

  3. Write router configuration items:

    //Introducing VueRouter
    import VueRouter from 'vue-router'
    //Introducing Luyou components
    import About from '../components/About'
    import Home from '../components/Home'
    
    //Create a router instance object to manage groups of routing rules
    const router = new VueRouter({
    	routes:[
    		{
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home
    		}
    	]
    })
    
    //Exposure router
    export default router
    
  4. Achieve switching (active class configurable highlight style)

    <router-link active-class="active" to="/about">About</router-link>
    
  5. Specify display location

    <router-view></router-view>
    

2. Several points for attention

  1. Routing components are usually stored in the pages folder, and general components are usually stored in the components folder.
  2. By switching, "hidden" routing components are destroyed by default and can be mounted when necessary.
  3. Each component has its own $route attribute, which stores its own routing information.
  4. There is only one router in the whole application, which can be obtained through the $router attribute of the component.

3. Multi level routing (multi-level routing)

  1. To configure routing rules, use the children configuration item:

    routes:[
    	{
    		path:'/about',
    		component:About,
    	},
    	{
    		path:'/home',
    		component:Home,
    		children:[ //Configure child routing through children
    			{
    				path:'news', //Be sure not to write: / news here
    				component:News
    			},
    			{
    				path:'message',//Do not write: / message here
    				component:Message
    			}
    		]
    	}
    ]
    
  2. Jump (to write the full path):

    <router-link to="/home/news">News</router-link>
    

4. query parameters of route

  1. Transfer parameters

    <!-- Jump and carry query Parameters, to String writing -->
    <router-link :to="/home/message/detail?id=666&title=Hello">Jump</router-link>
    				
    <!-- Jump and carry query Parameters, to Object writing method of -->
    <router-link 
    	:to="{
    		path:'/home/message/detail',
    		query:{
    		   id:666,
                title:'Hello'
    		}
    	}"
    >Jump</router-link>
    
  2. Receiving parameters:

    $route.query.id
    $route.query.title
    

5. Named route

  1. Function: it can simplify the jump of route.

  2. How to use

    1. Name the route:

      {
      	path:'/demo',
      	component:Demo,
      	children:[
      		{
      			path:'test',
      			component:Test,
      			children:[
      				{
                            name:'hello' //Name the route
      					path:'welcome',
      					component:Hello,
      				}
      			]
      		}
      	]
      }
      
    2. Simplified jump:

      <!--Before simplification, you need to write a complete path -->
      <router-link to="/demo/test/welcome">Jump</router-link>
      
      <!--After simplification, jump directly through the name -->
      <router-link :to="{name:'hello'}">Jump</router-link>
      
      <!--Simplified writing fit transfer parameters -->
      <router-link 
      	:to="{
      		name:'hello',
      		query:{
      		   id:666,
                  title:'Hello'
      		}
      	}"
      >Jump</router-link>
      

6. params parameters of route

  1. Configure the route and declare to receive params parameters

    {
    	path:'/home',
    	component:Home,
    	children:[
    		{
    			path:'news',
    			component:News
    		},
    		{
    			component:Message,
    			children:[
    				{
    					name:'xiangqing',
    					path:'detail/:id/:title', //Receive params parameters using placeholder declarations
    					component:Detail
    				}
    			]
    		}
    	]
    }
    
  2. Transfer parameters

    <!-- Jump and carry params Parameters, to String writing -->
    <router-link :to="/home/message/detail/666/Hello">Jump</router-link>
    				
    <!-- Jump and carry params Parameters, to Object writing method of -->
    <router-link 
    	:to="{
    		name:'xiangqing',
    		params:{
    		   id:666,
                title:'Hello'
    		}
    	}"
    >Jump</router-link>
    

    Special note: when the route carries params parameters, if the object writing method of to is used, the path configuration item cannot be used, but the name configuration must be used!

  3. Receiving parameters:

    $route.params.id
    $route.params.title
    

7. props configuration of routing

Function: make it easier for routing components to receive parameters

{
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//The first way to write it: props value is an object, and all key value combinations in the object will eventually be passed to the Detail component through props
	// props:{a:900}

	//The second method: if the props value is Boolean and the Boolean value is true, all params parameters received by the route will be passed to the Detail component through props
	// props:true
	
	//The third way to write: props value is a function, and each group of key values in the object returned by this function will be passed to the Detail component through props
	props(route){
		return {
			id:route.query.id,
			title:route.query.title
		}
	}
}

8. replace attribute of < router link >

  1. Function: control the mode of operating browser history during route jump
  2. There are two ways to write browser history: push and replace. Push is to add history and replace is to replace the current record. The default value for route jump is push
  3. How to start the replace mode: < router link replace........ > News</router-link>

9. Programmed route navigation

  1. Function: realize route jump without the help of < router link >, making route jump more flexible

  2. Specific code:

    //Two API s of $router
    this.$router.push({
    	name:'xiangqing',
    		params:{
    			id:xxx,
    			title:xxx
    		}
    })
    
    this.$router.replace({
    	name:'xiangqing',
    		params:{
    			id:xxx,
    			title:xxx
    		}
    })
    this.$router.forward() //forward
    this.$router.back() //back off
    this.$router.go() //You can go forward or backward. The parameter is of type number (positive number is the number of steps forward and negative number is the deployment backward)
    

10. Cache routing component

  1. Function: keep the routing components not displayed mounted and not destroyed.

  2. Specific code:

    <keep-alive include="News"> 
        <router-view></router-view>
    </keep-alive>
    

11. Two new life cycle hooks

  1. Function: two hooks unique to the routing component, which are used to capture the activation status of the routing component.
  2. Specific name:
    1. Triggered when the activated routing component is activated.
    2. Triggered when the deactivated routing component is deactivated.

12. Route guard

  1. Function: to control the routing permission

  2. Classification: Global guard, exclusive guard and in component guard

  3. Global guard:

    //Global front guard: executed during initialization and before each route switching
    router.beforeEach((to,from,next)=>{
    	console.log('beforeEach',to,from)
    	if(to.meta.isAuth){ //Judge whether the current route needs permission control
    		if(localStorage.getItem('school') === 'atguigu'){ //Specific rules for permission control
    			next() //Release
    		}else{
    			alert('No permission to view')
    			// next({name:'guanyu'})
    		}
    	}else{
    		next() //Release
    	}
    })
    
    //Global post guard: executed during initialization and after each route switching
    router.afterEach((to,from)=>{
    	console.log('afterEach',to,from)
    	if(to.meta.title){ 
    		document.title = to.meta.title //Modify the title of the page
    	}else{
    		document.title = 'vue_test'
    	}
    })
    
  4. Exclusive guard:

    beforeEnter(to,from,next){
    	console.log('beforeEnter',to,from)
    	if(to.meta.isAuth){ //Judge whether the current route needs permission control
    		if(localStorage.getItem('school') === 'atguigu'){
    			next()
    		}else{
    			alert('No permission to view')
    			// next({name:'guanyu'})
    		}
    	}else{
    		next()
    	}
    }
    
  5. Guard inside the assembly:

    //Entry guard: it is called when entering the component through routing rules
    beforeRouteEnter (to, from, next) {
    },
    //Leave guard: it is called when leaving the component through routing rules
    beforeRouteLeave (to, from, next) {
    }
    

13. Two working modes of router

  1. What is a hash value for a url# And what follows is the hash value.
  2. The hash value will not be included in the HTTP request, that is, the hash value will not be brought to the server.
  3. hash mode:
    1. It's not beautiful with the address # in the middle.
    2. If the address is shared through a third-party mobile app in the future, if the app verification is strict, the address will be marked as illegal.
    3. Good compatibility.
  4. history mode:
    1. The address is clean and beautiful.
    2. Compatibility is slightly worse than hash mode.
    3. When the application is deployed online, it needs the support of back-end personnel to solve the problem of refreshing the page server 404.

Topics: Javascript Front-end Vue.js