vue learning notes

Vue.js learning notes

First stop

Initial use

js

// Let / const how to create variables
const app = new Vue({
    el:'#app ', / / used to mount elements to be managed
    data:{  // Define data
        message: 'How do you do!',
        name: 'hello How do you do'
    },
    // Method area, in which methods can be called in HTML
    methods: {
        // Define a click method
        click: function() {
            alert("Hello")
        }
    },
    // Calculation properties
    computed: {
        upChar(message) {
            message.up
        }
    }
    // Execute this zone method before the web page is created
    beforeCreate: function (){
        console.log("beforeCreate");
    },
    // Execute this zone method after the web page is created
    created: function() {
        console.log("created");
    },
    // 
    mounted: function() {
        console.log("mounted");
    },
})

In HTML

<!-- app Module name and vue Used in el Consistent mount name -->
<div id="app">
    <!-- moustache grammar:
			use: {}To introduce data Data in
			moustache Simple calculations can be used in: + - * /
	-->
    <h2>{{message}}</h2>
    <h1>{{name}}</h1>
</div>
<!-- Import vue modular -->
<script src="../js/vue.js"></script>

Primary grammar

  • v-on: used to bind events
    • Syntax: "@"
    • example:
      • v-on:click="click"
      • @click="click"
  • v-for="item in movies" traverse every data in the array moves, and item is every data
  • v-html="url" is displayed in HTML
  • v-text="message" displayed as text
  • v-pre displays the contents of the label intact
  • v-cloak displays the label content only after the vue code is executed
  • After v-once modification, the content will not change, only the first value will be displayed
  • v-bind dynamic binding
    • Syntax:
    • example:
      • v-bind:style="color:blue";
      • :style="color:blue";

assembly

  • Create a component (similarly, the component also has its own data field, which can be used like the attributes of vue instances, but the data attribute in the component must be a function)

    const cpn1 = Vue.extend({
    	template: `
    		<div>
                <h1>Component 1</h1>
    		</div>
    	`,
    	data() {
    		return {
    			message: "hello"
    		}
    	}
    })
    
  • Register components

    • Global registration component

      			// Component name component instance
      Vue.component('my-cpn', cpn1)
      
    • Grammatical sugar writing

      Vue.component('my-cpn', {
      	template: `
      		<div>
                  <h1>Component 1</h1>
      		</div>
      	`
      })
      
    • Local registration component

      Vue({
      	el: "#app",
      	components: {
      		//Component name component instance
      		my-cpn: cpn1
      	},
      	data: {
      		message: "Hello"
      	}
      })
      
  • Using components (components created must be within Vue managed instances)

    <div id="app">
        <!--Can be used multiple times-->
        <my-cpn></my-cpn>
    </div>
    
  • Create subcomponents in components

    Vue.extend({
    	template: `
    		<div>
    			<div>Parent component</div>
    			<cpn1></cpn1>      
    		</div>
    	`,
    	components: {
    		cpn1: cpn1
    	}
    })
    
  • Extract the template from js and put it into the html tag

    • Method 1:

      <!--Write template to script In the label, script Type must be: text/x-template-->
      <script type="text/x-template" id="cpn">
      	<div>I'm a component</div>
      </script>
      
    • Mode 2:

      <template id="cpn">
          <div>I'm a component</div>
      </template>
      
  • Register components

    Vue.component("cpn", {
    	template: "#cpn"
    })
    

Second stop

Communication between parent and child components

  • Passing information to subcomponents

    <body>
        <div id="app">
            <div>{{message}}</div>
        <!--The name of the accepted information in the subcomponent is hello, hello2,The name of the data information passed in the parent component is message,message2-->
        <!--If not used v-bind(:)The string will be message and message2 Passed to child components, not·Information in parent component-->
            <cpn :hello="message" :hello2="message2" :child-message-info="info"/>
        </div>
    </body>
    
    <template id="cpn">
        <!--vue2 The template must contain a root tag-->
        <div>
            <div>I am a subcomponent</div>
            <div>Information in parent component:</div>
            <div>{{hello}}</div>
            <div>{{hello2}}</div>
            <div>{{childMessageInfo}}</div>
        </div>
    </template>
    
    <script>
        cpn = {
            template: "#cpn",
            // It is used to store the information passed in the parent component
            // Mode 1:
            props: ['hello', 'hello2']
            // Method 2: (at this time, the information types transmitted to the sub components are limited, here is the string type)
            props: {
            	hello: string,
            	hello2: string
        	}
        	// Method 3: (at this time, not only the type is limited, but also the default value. When the parent component does not send information, the default value will be used)
        	props: {
                hello: {
                    type: string,
                    default: "I'm the default",
                    // Indicates that information must be passed
                    required: true
                },
                hello2: {
                    type: Array,
                    // An error will be reported when the default value is []
                    // default: []
                    // When the type is an object or array, the default value must be a function
                    default() {
    					return []
                    }
                }
                // When the sub information receiving variable is hump identification variable, it shall be indicated by adding "-" in other places
                childMessageInfo: {
                    type: Object,
                    default() {
                        return {}
                    }
                }
            }
        }
    
        new Vue({
            el: "#app",
            components: {
                cpn
            },
            data: {
                message: "Hello, I'm the parent component",
                message2: "Hello, this is the second message",
                info: {
                	name: "Zhang San",
                	age: 18
            	}
            }
        })
    </script>
    
  • Pass information to parent component

    <body>
        <div id="app">
            <!--Bind the name of the event emitted by the subcomponent to the listening function. The bound here is childClick event-->
            <!--vue2 Hump writing cannot be resolved in, but in vue Can be resolved in scaffold-->
            <cpn @item-click="childClick"></cpn>
        </div>
    </body>
    
    <template id="cpn">
        <div>
            <h1>I am a subcomponent</h1>
            <!--When the button is clicked, the function is triggered to send events-->
            <button v-for="item in categories"
                    @click="btnClick(item)">{{item.name}}</button>
        </div>
    </template>
    <script>
    
        const cpn = {
            template: "#cpn",
            data() {
                return {
                    categories: [
                        {id: '01', name: 'Mobile digital'},
                        {id: '02', name: 'Household Electric Appliances'},
                        {id: '03', name: 'Clothing decoration'},
                        {id: '04', name: 'Practical small pieces'}
                    ]
                }
            },
            methods: {
                btnClick(item) {
                    // Launch event (user-defined event). The name of the launch event is the first parameter, and the second parameter is the sent content
                    this.$emit('item-click', item)
                }
            }
        }
    
        new Vue({
            el: "#app",
            components: {
                cpn
            },
            date: {
                message: "Child to parent communication between parent and child components"
            },
            methods: {
                // The variables received here by default are those sent by the subcomponent
                childClick(item) {
                    console.log("Received", item)
                }
            }
        })
    </script>
    

watch

  • watch is used to listen for property changes

    <body>
        <div id="app">
            <div>{{message}}</div>
        </div>
    </body>
    <script src="vue/vue.js"></script>
    <script>
        const app = new Vue({
            el: "#app",
            data: {
                message: "hello world"
            },
            watch: {
                // Here, the watch function name must be the data name in data, where newVal and oldVal are the new value and old value respectively
                message(newVal, oldVal) {
                    console.log(newVla, oldVal)
                }
            }
        })
    </script>
    

Access mode of parent-child components

Parent component accessing child components:

​ c h i l d r e n : t h i s . children: this. children: this.children is an array type that contains all child component objects

​ $refs

Child component access parent component:

​ $parent

  • The parent component calls the method in the child component

    <body>
        <div id="app">
            <!--adopt ref Property to use the subcomponent in the component-->
            <cpn ref="cpn1"></cpn>
            <cpn ref="cpn2"></cpn>
            <button @click="btnClick">Call from component method</button>
        </div>
    </body>
    
    <template id="cpn">
        <div>Subcomponents</div>
    </template>
    <script>
    
        const cpn = Vue.component("cpn", {
            template: "#cpn",
            data() {
                return {
                    message: "I am the information in the subcomponent"
                }
            },
            methods: {
                showMSG() {
                    alert("Call succeeded!")
                }
            }
        })
    
        new Vue({
            el: "#app",
            components: {
                cpn
            },
            data: {
                message: "hello world"
            },
            methods: {
                btnClick() {
                    // Generally, $refs is used instead of the $children attribute
                    this.$children[0].showMSG()
                    alert(this.$children[0].message)
                    // This method is recommended
                    this.$refs.cpn1.showMSG()
                    console.log(this.$refs.cpn2.message)
                }
            }
        })
    </script>
    
  • The child component calls the method in the parent component

    <body>
        <div id="app">
            <cpn></cpn>
        </div>
        <template id="cpn">
            <div>
                <div>I am a subcomponent</div>
                <button @click="btnClick">Call method in parent component</button>
            </div>
        </template>
    </body>
    <script>
        const cpn = Vue.component("cpn", {
            template: "#cpn",
            methods: {
                btnClick() {
               // Use the $parent attribute to access the parent component, but this method is not recommended (there may be multiple parent components due to high coupling)
                    this.$parent.showMSG()
                    console.log(this.$parent.message);
                    // Access to the root component uses $root. In this example, $parent is the same as $root
                    console.log(this.$root.message)
                }
            }
        })
    
        new Vue({
            el: "#app",
            components: {
                cpn
            },
            data: {
                message: "Hello, I'm the parent component"
            },
            methods: {
                showMSG() {
                    alert("Access succeeded!")
                }
            }
        })
    </script>
    

slot

Using slots in functional components with similar structure can bring great convenience

  • Define slot

    <body>
        <div id="app">
            <cpn><button>Introduced through slot button Button</button></cpn>
            <cpn><a>Add by slot a label</a></cpn>
            <cpn></cpn>
        </div>
        <template id="cpn">
            <div>
                <div>Subcomponents</div>
           <!--When a component contains multiple slots, they are all used by name, and the slots in the component will be replaced by the contents in the component-->
                <slot></slot>
                <!--This slot contains a default value. When this slot is introduced, if no element is added to the component, it will be added to the element by default. If there are elements, the default element will be replaced with the specified element-->
                <slot><button></button></slot>
            </div>
        </template>
    </body>
    <script>
        const cpn = {
            template: "#cpn"
        }
    
        new Vue({
            el: "#app",
            components: {
                cpn
            }
        })
    </script>
    
  • Named slot

    <body>
        <div id="app">
            <!--Use when replacing slot Property to replace a slot with a specific name. The scope of the slot only works under a template. Here input Will not be displayed because isShow stay vue In the instance false Therefore, it will not be displayed-->
            <cpn><input v-show="isShow" slot="center"/></cpn>
        </div>
        <template id="cpn">
            <div>
                <!--When using a named slot, you must select the name of the slot to replace-->
                <slot name="left"><span>left</span></slot>
                <slot name="center"><span>middle</span></slot>
                <slot name="right"><span>right</span></slot>
            </div>
        </template>
    </body>
    <script>
        const cpn = {
            template: "#cpn",
            data() {
                return: {
                    isShow: true
                }
            }
        }
    
        new Vue({
            el: "#app",
            components: {
                cpn
            },
            data: {
                isShow: false
            }
        })
    </script>
    
  • Reference the data in the child component in the parent component

    <body>
        <div id="app">
            <cpn></cpn>
            <cpn>
               <!-- In 2.5.x Must be used before template Template, in 2.5.x Later, this constraint is cancelled and data is referenced in the template -->
                <template slot-scope="slot">
                    <span v-for="item in slot.data">{{item}} --- </span>
                </template>
            </cpn>
            <cpn>
                <!-- among slot-scope It is a fixed writing method, and the subsequent value is the referenced sub component -->
                <div slot-scope="sl">
                    <!-- From subcomponents data Domain value -->
                    <a href="#" v-for="item in sl.data">  --{{item}}--  </a>
                </div>
            </cpn>
            
            <cpn2></cpn2>
            <cpn2>
                <div slot-scope="s">
                    <!--join Function will be used in the middle of the array - To split-->
                    <!-- Due to the use of message To store variables, so it must also be used when referencing message -->
                    <i>{{s.message.join(' - ')}}</i>
                </div>
            </cpn2>
        </div>
        <template id="cpn">
            <div>
                <div>I am a subcomponent</div>
                <!--data You can name yourself, you can data Change to another variable name. You must also use another variable name when referencing-->
                <slot :data="arr">
                    <ul>
                        <li v-for="item in arr">{{item}}</li>
                    </ul>
                </slot>
            </div>
        </template>
        <template id="cpn2">
            <div>
                <div>I am sub component 2</div>
                <slot :message="arr">
                    <ul>
                        <li v-for="item in arr">{{item}}</li>
                    </ul>
                </slot>
            </div>
        </template>
    </body>
    <script>
        new Vue({
            el: "#app",
            components: {
                cpn: {
                    template: "#cpn",
                    data() {
                        return {
                            arr: ['java', 'c', 'c++', 'php']
                        }
                    }
                },
                cpn2: {
                    template: "#cpn2",
                    data() {
                        return {
                            arr: ['Tomatoes', 'tomato', 'Pumpkin', 'White gourd']
                        }
                    }
                }
            }
        })
    </script>
    

In vue-cli3 and above versions, the following methods shall be used for slot use

<!-- Use here v-slot: To specify a named slot -->
<template v-slot:header>
	<h1>Here might be a page title</h1>
</template>

<template v-slot:footer>
	<p>Here's some contact info</p>
</template>

life cycle

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-GFZaIs0n-1626776658174)(D:\Dahui\DesktopApp \ learning materials \ learning notes \ front end \ JavaScript forgetting knowledge points \ Vue.js\Vue.js learning notes \ img\lifecycle.png)]

Modular development

  • commonjs syntax

    • a.js

      let name = "Xiao Ming"
      let age = 18
      
      let sayHello = function () {
          console.log("hello: " + name)
      }
      
      modlue.export = {
          name,
          age,
          sayHello
      }
      
    • b.js

      let name = "Xiao Hong"
      let age = 19
      
      let sayHello = () => {
          console.log("hello: " + name)
      }
      
      modlue.exports = {
          name,
          age,
          sayHello
      }
      
    • main.js

      let {name, age, sayHello} = require("./a.js")
      
    • Use in main page

      <!--Add on import type Properties will not have naming conflicts-->
      <script src="main.js" type="module"></script>
      <script src="a.js" type="module"></script>
      <script src="b.js" type="module"></script>
      
  • ES6 syntax

    • a.js

      let name = "Xiao Ming"
      let age = 18
      
      let sayHello = (msg) => {
          console.log("hello, " + msg)
      }
      
      // Export method 1:
      export { name, age, sayHello }
      // Export method 2: (when defining variables, export directly)
      export let num = 1
      // derived function
      export function sum(num1, num2) {
          return num1 + num2
      }
      // Export class
      // ES5 syntax
      export function Person() {
          let name
          let age
      }
      // ES6 syntax
      export class Person{
          let name
          let age
      }
      
      // (for the above export methods, you can only use the name when exporting in other files.)
      // Export default can be unnamed during export. There can only be one export default in a file. When importing, you can rename
      export default Perosn
      
    • b.js

      import {name, age, sayHello} from './a.js'
      // At this time, the default export data of the export file is imported, which can be renamed during import
      import presonA from './a.js'
      // At this time, it is imported and stored in an obj object. When accessing, you can use "obj "Form of
      import * as obj from './a,js'
      
      console.log(obj.name)
      
      (() => {
          console.log(name + "The age of the students is:" + age)
      })()
      
      sayHello(name + ",pet name:")
      

Packaging with webpack

Initial use

The instruction webpack is used when packaging/ src/main. js -o ./ dist/

If the webpack is above 4.0, the - o option should be used to specify the output address. In previous versions, the - o option is not required. It is not necessary to specify the name of the output file. If it is specified, it will be displayed in the form of a folder and a main. File will be generated by default JS file

When packaging, you only need to specify the entry file, and other js files do not need to be packaged

webpack configuration

The configuration file name of webpack is fixed as webpack config. js

During configuration, it is necessary to introduce node related packages to dynamically obtain paths. It is necessary to execute npm init instruction at the terminal to generate a package JSON file

  • webpack.config.js

    // Obtain the absolute path through the module introducing node
    const path = require('path')
    
    module.exports = {
        // Imported entry
        entry: './src/main.js',
        // Exported exit
        output: {
            // It is required that path must be an absolute path, and the resolve function of path can dynamically obtain the path
            // __ dirname is the global variable of node. The join function can be used to splice two paths. Here is the absolute path and 'dist' path of the file
            // In webpack4 0 used the resolve function to splice paths
            path: path.join(__dirname, 'dist'),
            filename: "bundle.js"
        }
    }
    
  • package.json

    Comment code snippets are not allowed in json files

    {
      "name": "meet",
      "version": "1.0.0",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        // A mapping is built here. At this time, only the build instruction needs to be executed to execute packaging (npm run build is executed at the terminal)
        // An instruction (build) is defined here. When the instruction is executed, the local search will be given priority. If the local search does not exist, the global search will be taken
        // The commands you type in the command window will be found globally
        "build": "webpack"
      },
      "author": "",
      "license": "ISC",
      "description": ""
    }
    
    • At this time, just click the webpack or npm run build command on the terminal to realize automatic packaging
  • Development time dependency: npm install webpack@3.6.0 --save-dev

  • Runtime dependency: npm install vue --save

  • Automatically generated package JSON file

    • package.json

      {
        "name": "meet",
        "version": "1.0.0",
        "main": "index.js",
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
          "build": "webpack --mode development",
            // Configure the webpack service startup instruction. Parameters: - open set self startup
          "server": "webpack-dev-serve --open"
        },
        "author": "",
        "license": "ISC",
        "description": "",
          // During development, the package downloaded through the -- save dev instruction will be saved here
        "devDependencies": {
          "webpack": "^3.6.0"
        },
          // Runtime dependency
        "dependencies": {
        
        }
      }
      

webpack loader

  • Download loader and loader configuration

  • Use the npm install package name -- save dev to download the corresponding loader, and then webpack config. JS

  • Then main js can rely on related css files or other js files. You only need to import the packaged js file after packaging, rather than in index Introducing css or other js files into HTML

  • webpack.config.js

    // Obtain the absolute path through the module introducing node
    const path = require('path')
    
    module.exports = {
        // Imported entry
        entry: './src/main.js',
        // Exported exit
        output: {
            // It is required that path must be an absolute path, and the resolve function of path can dynamically obtain the path
            // __ dirname is the global variable of node. The resolve function can be used to splice two paths. Here is the absolute path and 'dist' path of the file
            path: path.join(__dirname, 'dist'),
            filename: "bundle.js"
        },
        module: {
            rules: [{
                // Regular expressions are used for matching, and the following two loader s will be used for matching
                test: /\.css$/,
                // CSS loader is only responsible for loading
                // The style loader is responsible for adding styles to the DOM
                // When using multiple loader s, load from right to left
                use: ['style-loader', 'css-loader']
            }, {
                test: /\.less$/i,
                use: [
                    // compiles Less to CSS
                    "style-loader",
                    "css-loader",
                    "less-loader",
                ],
            }]
        }
    }
    

webpack.config.js detailed configuration

An error may be reported when importing vue directly: prompt that you are using runtime only. This template cannot be compiled. You should use compiler included. To solve this problem, you need to go to webpack config. Configuration vue information in JS

// Obtain the absolute path through the module introducing node
const path = require('path')
// Import the package of webpack, and then you can import the plug-in of webpack
const webpack = require("webpack")
// Import automatically generated index HTML plugin
const HtmlWebPackPlugin = require('html-webpack-plugin')
// Import the auto ugly js code plug-in
const uglifyJsPlugin = require("uglifyjs-webpack-plugin")

module.exports = {
    // Imported entry
    entry: './src/main.js',
    // Exported exit
    output: {
        // It is required that path must be an absolute path, and the resolve function of path can dynamically obtain the path
        // __ dirname is the global variable of node. The resolve function can be used to splice two paths. Here is the absolute path and 'dist' path of the file
        path: path.join(__dirname, 'dist'),
        filename: "bundle.js",
        // When the file is packaged, there will be a path error for the file imported through css or other files. At this time, a public address needs to be configured. When other files are loaded, the public address will be spliced automatically
        publicPath: "dist/"
    },
    module: {
        rules: [{
            // Regular expressions are used for matching, and the following two loader s will be used for matching
            test: /\.css$/,
            // CSS loader is only responsible for loading
            // The style loader is responsible for adding styles to the DOM
            // When using multiple loader s, load from right to left
            use: ['style-loader', 'css-loader']
        }, {
            test: /\.less$/i,
            use: [
                // compiles Less to CSS
                "style-loader",
                "css-loader",
                "less-loader",
            ],
        }, {
            test: /\.(png|jpg|gif|jpeg|webp)$/i,
            use: [{
                loader: 'url-loader',
                // Limit the size of the file introduced by the url. The unit here is bytes and the size here is 8kb
                options: {
                    // When the loaded image is less than the limit, the image will be compiled into base64 string form
                    limit: 1000,
                    // Here, the file naming method "[]" is set for the packaged file, indicating the meaning of variable. Here, the packaged file is stored in the img folder, and the name is the name of the original file. 8 is the hash value Extension
                    name: 'img/[name].[hash:8].[ext]'
                }
            }],
        }, {
            test: /\.(png|jpe?g|gif|webp)$/i,
            use: [{
                loader: 'file-loader'
            }],
        }, {
            // This loader is a loader that converts es6 to es5
            test: /\.m?js$/,
            // exclude, the following files will not be used by this loader
            exclude: /(node_modules|bower_components)/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-env']
                }
            }
        },{
            test: /\.vue$/,
            use: ['vue-loader']
        }]
    },
    resolve: {
        // Using this configuration eliminates the file extension
        extensions: ['.js', '.vue', '.css'],
        // Alias: alias. When vue is introduced, vue will be found in the specified folder. When this configuration is added, the problem that the template cannot be loaded will be solved
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    },
    plugins: [
        // This plug-in can add copyright notes to each packaged file
        new webpack.BannerPlugin("The final copyright belongs to Xiao Ming"),
        // This plug-in will automatically generate the index after packaging HTML file, there will be no need to configure the publicPath path path at this time
        new HtmlWebPackPlugin({
            // According to index Generate index.html template HTML file
            template: "index.html"
        }),
        // Using the ugly plug-in, the js code will be automatically ugly after packaging to compress the js file
        new uglifyJsPlugin()
    ],
    // This configuration is only required during development and can be deleted during publishing
    devServer: {
        // Specify the folder for the service
        contentBase: "./dist",
        // Specifies whether to listen in real time
        inline: true,
        // Specify the server port. The default is port 8080
        port: 8080
    }
}
  • When there are both El attribute and template attribute in the vue instance, template will replace everything mounted by el

  • App.vue

    <template>
        <h1>{{message}}</h1>
    </template>
    
    <script>
    export default {
        name: "App",
        data() {
            return {
                message: "hello world"
            }
        }
    }
    </script>
    
    <style scoped>
        body {
            background-color: green;
        }
    </style>
    
  • main.js

    // Introduction of vue module
    import Vue from 'vue'
    
    // Import components
    import App from './vue/App'
    
    new Vue({
        el: "#app", 
        // At this point, the template template will replace el the mounted content
        template: "<App/>",
        components: {
            // Component mount
            App
        }
    })
    
  • webpack. config. Separation of JS files

    • base.config.js basic configuration

      // Obtain the absolute path through the module introducing node
      const path = require('path')
      
      // Import the package of webpack, and then you can import the plug-in of webpack
      const webpack = require("webpack")
      
      // Import automatically generated index HTML plugin
      const HtmlWebPackPlugin = require('html-webpack-plugin')
      
      module.exports = {
          // Imported entry
          entry: './src/main.js',
          // Exported exit
          output: {
              // It is required that path must be an absolute path, and the resolve function of path can dynamically obtain the path
              // __ dirname is the global variable of node. The resolve function can be used to splice two paths. Here is the absolute path and 'dist' path of the file
              // After the webpack configuration file is separated, the packaging path needs to be modified and added before the second parameter/
              // path: path.join(__dirname, 'dist'),
              path: path.join(__dirname, '../dist'),
              filename: "bundle.js",
              // When the file is packaged, there will be a path error for the file imported through css or other files. At this time, a public address needs to be configured. When other files are loaded, the public address will be spliced automatically
              publicPath: "dist/"
          },
          module: {
              rules: [{
                  // Regular expressions are used for matching, and the following two loader s will be used for matching
                  test: /\.css$/,
                  // CSS loader is only responsible for loading
                  // The style loader is responsible for adding styles to the DOM
                  // When using multiple loader s, load from right to left
                  use: ['style-loader', 'css-loader']
              }, {
                  test: /\.less$/i,
                  use: [
                      // compiles Less to CSS
                      "style-loader",
                      "css-loader",
                      "less-loader",
                  ],
              }, {
                  test: /\.(png|jpg|gif|jpeg|webp)$/i,
                  use: [{
                      loader: 'url-loader',
                      // Limit the size of the file introduced by the url. The unit here is bytes and the size here is 8kb
                      options: {
                          // When the loaded image is less than the limit, the image will be compiled into base64 string form
                          limit: 1000,
                          // Here, the file naming method "[]" is set for the packaged file, indicating the meaning of variable. Here, the packaged file is stored in the img folder, and the name is the name of the original file. 8 is the hash value Extension
                          name: 'img/[name].[hash:8].[ext]'
                      }
                  }],
              }, {
                  test: /\.(png|jpe?g|gif|webp)$/i,
                  use: [{
                      loader: 'file-loader'
                  }],
              }, {
                  // This loader is a loader that converts es6 to es5
                  test: /\.m?js$/,
                  // exclude, the following files will not be used by this loader
                  exclude: /(node_modules|bower_components)/,
                  use: {
                      loader: 'babel-loader',
                      options: {
                          presets: ['@babel/preset-env']
                      }
                  }
              },{
                  test: /\.vue$/,
                  use: ['vue-loader']
              }]
          },
          resolve: {
              // Using this configuration eliminates the file extension
              extensions: ['.js', '.vue', '.css'],
              // Alias: alias
              alias: {
                  'vue$': 'vue/dist/vue.esm.js'
              }
          },
          plugins: [
              // This plug-in can add copyright notes to each file
              new webpack.BannerPlugin("The final copyright belongs to Xiao Ming"),
              // This plug-in will automatically generate the index after packaging HTML file
              new HtmlWebPackPlugin({
                  // According to index Generate index.html template HTML file
                  template: "index.html"
              })
          ]
      }
      
    • dev.config.js development time dependent configuration

      const webpackMerge = require("webpack-merge")
      const baseConfig = require("./base.config")
      
      module.exports = new webpackMerge(baseConfig, {
          devServer: {
              // Specify the folder for the service
              contentBase: "./dist",
              // Specifies whether to listen in real time
              inline: true,
              // Specify the server port. The default is port 8080
              port: 8080
          }
      })
      
    • pro.config.js project depends on when publishing

      const webpackMerge = require("webpack-merge")
      
      // Import the auto ugly js code plug-in
      const uglifyJsPlugin = require("uglifyjs-webpack-plugin")
      const baseConfig = require("./base.config")
      
      module.exports = (baseConfig, {
          plugins: [
              // Using the ugly plug-in, the js code will be automatically ugly after packaging to compress the js file
              new uglifyJsPlugin()
          ]
      })
      
    • In this case, you need to enter package Add webpack. JSP to the JSON file config. JS file, otherwise an error will be reported, and the configuration file of webpack cannot be found

      "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
          // --config specifies the path
          "build": "webpack --mode development --config ./build/pro.config.js",
          "dev": "webpack-dev-serve --config ./build/dev.config.js"
        }
      

Third stop

vue-cli

If you are using the version of vue - cli 2, use the command: vue init webpack project name to create

vue - cli higher version creation command: vue create item name creation

render function

vue execution principle:

runtime - complier execution principle:

​ tempalte --> ast(abstract tree) --> render --> virtual dom --> UI

runtime - only execution principle:

​ render --> virtual dom --> UI

// Create an object using the render function
render: function (createELement) {
    retun createELement('div',
     {class: 'box'},
     ['I am by render Function to render the label', createELement('button', {id: 'btn'}, ['Button'])])
  }


// Pass in the component object using the render function
const cpn = {
    template: '<div>{{message}}</div>',
    data() {
        return {
            message: "I'm a component"
        }
    }
}
render: function (createELement) {
    retun createELement(cpn)
  }

In vue3, the configuration file is hidden by default. If you want to import your own configuration, you need to create: Vue config. JS file, the file name is fixed

vue.config.js

module.export = {
    ...
}

Vue - Router

Prelude:

There are some ways to change the url, but the page does not refresh

Use location hash = ‘a’; You can add a after the address bar, that is, the original is www.baidu.com Com can be transformed into: www.baidu.com com/a

Use history Pushstate ({}, '' and 'a') can achieve the same effect as hash. This method is to put the newly added connection into the stack and then use history Back() function, it will return layer by layer

  • Parameters:
  • data
  • title
  • url

history.replaceState({}, ',' b ') in this way, the original url will be overwritten and cannot be returned to the previous page through the back() function

history.back() returns to the previous page

history.go()

  • history.go(-1) and history Back() equivalent
  • history.go(-2) will pop up two addresses in the stack, that is, return twice
  • history.forword() is equivalent to history go(1)
  • history.go(2) will be pushed into two addresses in the stack, that is, forward twice

Vue router configuration

Create the router folder in the src directory, and create the index JS file, which configures routing related information

router – > index. JS (vue3 and below)

// The import vue is used to register components in subsequent
import Vue from 'vue'
// Import route, used to configure route related information
import VueRouter from 'vue-router'

// Install plug-ins
Vue.use(VueRouter)

// Import components
import App from '../App.vue'
import About from '../components/About'
import Profile from '../components/Profile.vue'

// Configure path related variables
const routes = [
    {
        path: '',
        // Use redirection to navigate to the / home path at the beginning of the page
        redirect: '/home'
    },{
		path: '/about',
		component: About
    },{
        // Use /: userId to dynamically splice url paths. In the Profile component, you can use: this$ route. params. userId gets the incoming userId information
		path: '/profile/:userId',
		component: Profile
    }]

// Create routing object
const router = new VueRouter({
    routes,
    // Change the default mode of the path. The default mode is hash (this mode will make the path contain #). Here, change the edge to history mode
    mode: 'history',
    // Change to the class name of the rendered label after clicking router link
    linkActiveClass: 'active'
})

// Export router
export default router

router – > index. JS (vue3 above usage)

// Import routing related objects
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

On app How to guide to this page in Vue

<template>
  <div id="app">
      <!-- router-link and router-view Label is router Automatically registered components can be used directly -->
    <!-- use router-link Label, which will change to by default after rendering a label -->
    <router-link to="/about">about</router-link>
    <!-- use tag Property changes the rendered result to button label, replace Property causes the path change to use substitution instead of stack pressing, that is, it cannot be returned -->
    <!-- When clicking on a router-link After rendering the label, vue Two are automatically added before the change class Class( router-link-active and router-link-exact-active),This class name can be used to set the style after clicking. Use active-class Property can be changed after the tag is clicked class Property, here change to active ,Can be in router Make changes uniformly in the configuration file-->
    <router-link to="/profile" tag="button" replace active-class="active">my</router-link>
      
      <!-- Change the of the page by url Page Jump -->
      <button @click="aboutClick">about</button>
      <button @click="profileClick">my</button>
      
      <!-- Dynamic splicing path, add dynamic path splicing information after the jump -->
      <router-link to="/profile/xiaoming">my</router-link>
      <!-- Dynamic splicing path, add dynamic path splicing information after the jump. Here is at data Search in userId variable -->
      <router-link :to="'/profile/' + userId">my</router-link>
      
      <!-- router-view Components will make router-link The point in the label is rendered here, that is, replace router-view label -->
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
      return {
          userId: 'xiaoming'
      }
  }
  methods: {
      // Click to listen for events
      aboutClick() {
          // Router injects a $router attribute into each component, which can jump the page
          this.$router.push('/about')
      },
      profileClick() {
          // Page Jump is performed through replace, and the page jumped by this method cannot be returned
          this.$router.replace('/profile')
      },
  }
}
</script>

Get the url path of user splicing in the sub component through this$ route. params. userId (userId is the dynamic variable set in the route) to obtain the route object that is active at this time

js files are divided through the lazy loading mechanism of routing, so that users will not have a short blank and unresponsive state when accessing for the first time, and a lazy loading will correspond to a packaged js file

There are three ways to load routes

  • Method 1 (combining asynchronous components of vue and code analysis of webpack) is not recommended:
const routes = [
  {
    path: '/',
    component: Home = resolve => {require.ensure(['../components/Home.vue'], () => {resolve(require('../components/'))} )}
  }
]
  • Method 2 (AMD writing method):
const routes = [
  {
    path: '/',
    component: Home = resolve => require(['../components/Home.vue'], resolve}
  }
]
  • Mode 3 (ES6) recommended:
const routes = [
  {
    path: '/',
    component: Home = () => import ('../components/Home.vue')
  }
]

// Better practice
const Home = () => import ('../components/Home.vue')

const routes = [
  {
    path: '/',
    component: Home
  }
]
  • Components are further subdivided to configure sub routes
const Home = () => import('../components/Home.vue')
const News = () => import('../components/News.vue')
const Fun = () => import('../components/Fun.vue')

const routes = [
  {
    path: '/',
    component: Home,
    // The children attribute is used to determine the information related to the sub component route of the component. The sub route does not need to add '/'
    children: [
      {
          path: 'news',
      	  component: News
      },{
          path: 'fun',
          component: Fun
      }
    ]
  }
]
  • In the parent component, add the router link and router view labels as in configuring the normal route, and set the display position and time of the child component
<template>
  <div id="app">
      <!-- Here is the path where you want to add the parent component -->
      <router-link :to="'/home/news">Journalism</router-link>
      
      <router-view/>
  </div>
</template>
  • Jump the interface and transfer parameters in another way
<template>
  <div id="app">
      <router-link :to="{path: '/profile', query: {name: 'xiaoming', age: 18}}">Journalism</router-link>
      
      <router-view/>
      
      <!-- adopt query To get the currently passed parameter object -->
      <div>{{$router.query}}</div>

</template>
  • Setting jump and parameter transfer through ordinary label
<template>
  <div id="app">
    <button @click="aboutClick">about</button>
    <button @click="profileClick">My 11</button>
      
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
      return {
          userId: 'xiaoming'
      }
  }
  methods: {
      // Click to listen for events
      aboutClick() {
          // Router injects a $router attribute into each component, which can jump the page
          this.$router.push('/about')
      },
      profileClick() {
          // Page Jump is performed through replace, and the page jumped by this method cannot be returned
          this.$router.push({
              path: '/profile',
              query: {
                  name: 'xiaoming',
                  age: 18
              }
          })
      },
  }
}
</script>

Route and route are not the same. Route represents the currently active routing object, and route represents the whole routing object

Extension:

  • Add a property to an object:

    const obj = {
        name: 'xiaoming'
    }
    
    // Through object The defineproperty () method adds properties to the object (this method is reactive)
    	// Parameter 1 is the object to add the attribute, parameter 2 is the added attribute name, and parameter 3 is the attribute value
    Object.defineProperty(obj, 'age', 18)
    
  • When the page jumps, the title name of the page in the table

    // This method will be called after the build is created. However, this method must be used in each component, so it is not recommended
    created() {
        // This method can change the title name of each web page
        document.title = "user"
    }
    
    // As a better practice, add the following code to the routing configuration file
    
    const routes = [
      {
        path: '/',
        component: Home = () => import ('../components/Home.vue'),
        // Add element data for each routing object to change the title name when jumping to the page
        meta: {
          title: 'home page'
        }
      }
    ]
    
    // These methods can also be written directly in each mapping relationship
    // Front guard
    router.beforeEach((to, from ,next) => {
        // From and to, i.e. jump from to
        // When there are nested routes, the parent route will not find the title attribute. In this case, set the title of the meta in the matched attribute
        document.titile = to.matched[0].meta.title
        
        // Next means the next step. This function must be called. When this function is not called, there will be no page transfer
        // Parameters can be passed in the next function. When the parameter is false, interrupt the current navigation or pass in a path, that is, jump to the path
        next()
    })
    
    // Rear hook
    router.afterEach((to, from) => {
        // There is no next parameter in the post hook, that is, this method will not be called until the page is skipped
    })
    

    Using the keep alive tag to nest the router view tag can not create and destroy frequently (because the components will be created and destroyed frequently during switching), but cache it, which will greatly improve the response time

  • Two properties of keep alive

    <!-- include String or regular expression, only matching components will be cached -->
    <!-- exclude String or regular expression, any matched component will not be cached -->
    <!-- Not cached here Home and Profile Component, where exclude The value of the property does not exist in each component name Property value, used by multiple components , No space is allowed between the segments -->
    <keep-alive exclude="Home,Profile">
    	<route-view/>
    </keep-alive>
    
    
    <!-- Not only cache here Home and Profile Component, where include The value of the property does not exist in each component name Property value, used by multiple components , No space is allowed between the segments -->
    <keep-alive include="Home,Profile">
    	<route-view/>
    </keep-alive>
    
  • When the page is skipped, the setting returns to the original page, and the display is the same before the page is skipped

    export default {
        name: 'home',
        data() {
            return {
                // The path variable is used to record the last active path, which can be used when jumping back later
                path: '/home/news'
            }
        },
        // This function is called when the page jumps, that is, before the route conversion
        beforeRouteLeave(to, from , next) {
            this.path = this.$route.path
            next()
        },
        // This function is called when the page is active
        activated() {
            this.$router.push(this.path)
        }
    }
    
  • activated and deactivated lifecycle functions

    export default {
        name: 'home',
        
        // Only when the component is kept alive can it be effective. Otherwise, these two functions will not be called automatically
        // This function is called when the page is active
        activated() {
            console.log('activated')
        },
        deactivated() {
            console.log('deactivated')
        }
    }
    

Configure the path mapping relationship in the file

  • In vue2 version, find webpack base. config. JS file (i.e. webpack configuration file), modify resolve and add the corresponding path mapping relationship
resolve: {
    alias: {
        '@': resolve('src')
        'assets': resolve('src/ssets'),
        'components': resolve('src/components'),
        'views': resolve('src/views')
    }
}
  • Because the related configuration files are hidden in vue3, you need to create a Vue. Exe in the root directory config. JS file (you need to restart the following items every time you modify the configuration file), write the following information in the file to configure the relevant path mapping relationship
module.exports = {
	configureWebpack: {
		resolve: {
			alias: {
				'assets': '@/assets',
				'components': '@/components',
				'views': '@/views'
			}
		}
	}
}

When importing in non import mode (for example, importing resource files, pictures, etc.), you need to add "~" in front of it, for example: ~ assets/img/1.jpg

Promise usage

  • Asynchronously requesting network data may lead to callback hell. Using Promise can simplify programming and make the code look clearer. The code only needs to be written in the then function
new Promise((resolve, reject) => {
    // Use setTimeout to simulate asynchronous operations
    setTimeout(() => {
        //Call the resolve function
        resolve()
    }, 1000)
}).then(() => {
    // The logical structure of the code is processed here
    console.log("hello xiaoming")

    // Returns a Promise object, which will be called later
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // Parameters can be passed in the resolve function and accepted in then
            resolve("hello xiaohong")
        }, 1000)
    })
    // The parameter in then is the parameter passed when the resolve function is called
}).then((data) => {
    console.log(data)

    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // resolve is called when successful, and reject is called when failed
            reject("err ^ ... ^")
        } ,1000)
    })
    // The then function is executed only when the resolve function is called, and the catch function is executed when the reject function is called
}).then(() => {
    console.log("hello xiaogang") // The second statement will not be executed
}).catch((err) => {
    console.log(err)
})  // The execution result of the program is to output a print statement every second
  • Another form of Promise
new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("hello xiaogang")
        // reject("err ^ ... ^")
    }, 1000)
    // In the then function, two parameters can be passed, one is the data return result and the other is the error information, that is, the data information return and error information printing can be completed at the same time in the then function
}).then(data => {
    console.log(data)
}, err => {
    console.log(err)
})
  • Promise multi-level call, single-level asynchronous abbreviation
new Promise((resolve, reject) => {
    // Use setTimeout to simulate asynchronous operation, which is only used in this stage of network request
    setTimeout(() => {
        resolve("hello xiaoming")
    }, 1000)
}).then((data) => {
    // The logical structure of the code is processed here
    console.log(data)

    // Returns the result after calling the resolve function. There is no asynchronous processing here. You can call the resolve function directly, modify the value of the data each time, and print it in the following calls
    return Promise.reject(data + "1") // The reject function is called here, that is, the following then will not be executed
    // You can also use throw directly to throw an exception
    // throw 'error'
}).then((data) => { // This function will not execute
    console.log(data)

    return Promise.resolve(data + "2")
}).then(data => { // This function will not execute
    console.log(data)
}, err => { // This function will execute
    console.log(err)
}) // The print result is Xiaoming \ n Xiaoming1
  • Promise further abbreviation
new Promise((resolve, reject) => {
    // Use setTimeout to simulate asynchronous operation, which is only used in this stage of network request
    setTimeout(() => {
        resolve("hello xiaoming")
    }, 1000)
}).then((data) => {
    // The logical structure of the code is processed here
    console.log(data)

    // Return the result after data processing without calling promise Resolve() function
    return data + "1"
}).then((data) => {
    console.log(data)

    return data + "2"
}).then(data => {
    console.log(data)
}, err => {
    console.log(err)
})
  • Promise.all() method
// Promise. The all method needs to pass in an array, and each array is used to encapsulate different network requests
Promise.all([
    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("Xiao Ming")
        }, 2000)
    }),
    
    new Promise((resolve, reject) => {
        setTimeout(() => {
        	resolve("Xiao Hong")
        }, 1000)
    })
    // The data object is an array, which is used to store the results of two asynchronous processing operations
]).then(data => {
    console.log(data[0])
    console.log(data[1])
}) // The result is Xiao Ming \ n Xiao Hong

The fourth stop

Vuex status manager

When multiple components want to use the same state (variable), vuex can be used to store the state in the state manager. In this way, multiple components can be directly taken from the State Manager (equivalent to a storage container of a global variable)

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-WKp5GoUB-1626776658179)(D:\Dahui\DesktopApp \ learning materials \ learning notes \ front end \ JavaScript forgetting knowledge points \ Vue.js\Vue.js learning notes \ img\flow.png)]

Related configuration of Vuex

In the src folder, create a price inquiry folder named store (meaning warehouse, used to store various statuses), and create index JS file

index.js(vue2.x)

// Import Vue to register components in subsequent
import Vue from 'vue'
// Import Vuex to create the object later
import Vuex from 'vuex'

// Register the plug-in
Vue.use(Vuex)

// Create Vuex object
const store = new Vuex.Store({
    // The state object is used to save the state (variable), and you only need to use this elsewhere$ store. state. Variable name to access the variable
    state: {
  	},
    // The only way to update the store status of vuex is through mutation
  	mutations: {
    },
    actions: {
    },
    // Similar to the calculation attribute in the component, if you want to use it after changing the status each time, you need to implement it here
    getters: {
    },
    // Used to divide modules
    modules: {
    }
})

// Export the created store object
export default store

In main JS

main.js

import Vue from 'vue'
import App from './App'
import store from './store/index.js'

new Vue({
    el: '#app',
    store,
    render: h => h(App)
})

In vue3 The following methods are used in X

  • index.js(vue3.x)
import { createStore } from 'vuex'

export default createStore({
  // State is used to store the state for sharing
  state: {
      count: 100
  },
  mutations: {
      // Use this method to modify the count variable. The modified method will automatically pass in a parameter state to access the variables in state
      decreasement(state) {
          state.count --
      },
      increasement(state) {
          state.count --
      }
  },
  actions: {
  },
  modules: {
  }
})

In main JS

  • main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App).use(store).use(router).mount('#app')

Modify the state in the State Manager

When modifying a state in the state manager, if you use this$ store. state. When variable name = value, which component has modified the state when it is not known in later debugging. In order to facilitate later maintenance, it should be changed in an official way

  • The figure shows how to change in the status manager
  • Devtools is a plug-in for debugging vue in the browser. Mutions can only handle synchronous operations. Operations such as asynchronous requests cannot be affected by the Action phase, otherwise devtools cannot track them

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-hRdMiLDQ-1626776658183)(D:\Dahui\DesktopApp \ learning materials \ learning notes \ front end \ JavaScript forgetting knowledge points \ Vue.js\Vue.js learning notes \ img\vuex.png)]

Modify the status by the following methods

  • App.vue
<template>
  <div id="app">
    <div>{{$store.state.count}}</div>
    <div>{{$store.getters.powerCounter}}</div>
    <div>{{$store.getters.length}}</div>
    <!-- Pass in parameters here to modify the status with parameters -->
    <div>{{$store.getters.mergeS('a')}}</div>

    <button @click="additionCount(5)">+5</button>
    <button @click="addition">+</button>
    <button @click="substract">-</button>
  </div>
</template>

<script>
export default {
  name: 'App',
  methods: {
    addition() {
      // Call the function in the state manager by submitting, and the parameter is the function to be called
      this.$store.commit('increment')
    },
    substract() {
      this.$store.commit('decrement')
    },
    additionCount(count) {
        // Parameters can be passed in the calls to the changes method by passing in the second parameter
        this.$store.commit("increasementCount", count)
        // Special submission method. When parameters are passed in this way, the passed past is actually an object, and parameters need to be used when accessing count 
        this.$store.commit({
            type: 'increasementCount',
            count
        })
    }
  }
}
</script>
  • index.js (vuex configuration file in store folder)
import { createStore } from 'vuex'

export default createStore({
  state: {
    count: 100,
    obj: {
        age: 18
    }
  },
  // The state is modified by functions in this object
  mutations: {
    // When called in the change method, it will automatically access the state object, which is a user-defined state
    increment(state) {
      state.count ++
    },
    decrement(state) {
      state.count --
    },
    increasementCount(state, count) {
        state.count += count
    },
    update(state) {
        // In 2 In version x, this property will not be added to the responsive system, but in later versions, this feature has been fixed and can be modified responsively
        state.obj['name'] = "xiaoming"
        // In vue, you can use vue The set () method adds an attribute to the object, which can be added to the responsive system. Parameter 1 is the object to be modified, parameter 2 is added to the attribute, and parameter 3 is the attribute value
        Vue.set(state.obj, 'name', 'xiaoming')
        // Using the delete keyword can delete an attribute in an object, but this method cannot be responsive
        delete state.obj.age
        // Instead, use Vue The delete () method can responsively delete an attribute in an object. Parameter 1 is the object to be modified and parameter 2 is the deleted attribute (Vue.2x)
        Vue.delete(state.obj, age)
    }
  },
  getters: {
      // Here, you can directly use the modified data and $store getters. Powercount to access
      powerCounter(state) {
          return state.count * state.count
      },
      // This method will pass in a getters by default, which is the getters defined here 
      length(state, getters) {
          return getters.powerCounter >= 10000 ? 10 : getters.powerCounter
      },
      mergeS(state) {
          // When this method is called, it returns a function, in which you can pass in a function, and the function can return the modified state through the passed in parameters
          return function(num) {
              return state.count + num
          },
              // More concise writing, but it is not recommended because it is not good to understand
              mergeS(state) {
              return num => state.count + num
          }
      }
  },
  actions: {
      // Define a method in which a parameter will be passed by default. The parameter is the created store object, and the parameter 2 is the passed in parameter
      aUpdate(context, payload) {
          // When modifying the state in the store object, you can only modify the parameters in the store object through changes
          // When asynchronous operations are executed, execute the methods in changes through actions. Only in this way can devtools dynamically track the state changes in the store object. When executing the methods in actions, use this$ store. dispatch("aUpate")
          setTimeout(() => {              
          	  context.commit("increment")
          }, 1000)
      },
      // A method to remind the outside that it has been successfully modified. Parameter 2 is a function passed during external submission: this$ store. Dispatch ("aupdate", () = > {console. Log ("it has been modified")})
      aUpdate(context, payload) {
          setTimeout(() => {              
          	  context.commit("increment")
              // Call this function
              payload()
          }, 1000)
      },
      // Another way is to pass parameters in this way as follows: this$ store. Dispatch ("update", {message: 'I am the message', success: () = > {console. Log ("it has been modified")})
      aUpdate(context, payload) {
          setTimeout(() => {              
          	  context.commit("increment")
              // Call this function
              payload.success()
          }, 1000)
      },
      // Another more elegant way
      aUpdate(context, payload) {
          retrun new Promise((resolve, reject) => {
              setTimeout(() => {              
                  context.commit("increment")
                  console.log(payload)
                  resolve("Pass on past information")
              }, 1000)
          })
      }
      // When calling this method elsewhere, the code is as follows
      this
      	.$store.dispath("aUpdate", "Carry past information")
    	.then(res => {
    		console.log(res)
		})
  },
      
      
  moduleA = {
    state: {
        name: "xiaoming"
    },
  	mutations: {
        updateName(state, payload) {
            state.name = payload
        }
    },
    actions: {
        // The context here is the module object
        updateName(context) {
            // When you use commit here, the method submitted is the method in the changes in the module
            context.commit("updateName", 'xiaogang')
        }
    },
    getters: {
        update(state) {
        	return state.name + "1"
    	},
        // Here getters is the getters
        update2(state, getters) {
        	return getters.update + "1"
    	},
        // Here getters is the getters and rootState is the root store object
        update3(state, getters, rootState) {
            // You can access the state of the root store object through rootState
        	return getters.update + rootState.count
    	}
    },
    modules: {}
  }

  moduleB = {
    state: {},
  	mutations: {},
    actions: {},
    getters: {},
    modules: {}
  }
  // Modules can be defined in this object, and state and other attributes can be defined in the module. Unlimited dolls can be set. When in use: this$ store. moduleA. Name, when calling the method in mutations: this$ Store ("updatename", "Xiaohong"), so don't repeat the changes in each module
// When using the methods in getters, it is also used directly: this$ store. getters. Update, so the methods defined in getters cannot be repeated
  modules: {
      moduleA: moduleA
      moduleB: moduleB
  }
})

The official recommendation is to extract attributes other than state and modules into external files. You only need to import them in the index. The corresponding modules in modules are extracted into the new modules folder

  • extend

When calling some functions in variations, the name of the function that may be called will be written incorrectly, which can be avoided by defining constants

Create the file changes - type. In the store folder JS file

mutations-type.js

export const INCREMENT = 'increment'
export const DECREMENT = 'increment'

The method name in the store folder can also be defined in this way

import { createStore } from 'vuex'
import {INCREMENT, DECREMENT} from './mutations-type.js'

export default createStore({
  state: {
  },
  // This method can reduce errors
  mutations: {
    [INCREMENT](state) {
      state.count ++
    },
    [DECREMENT](state) {
      state.count --
    },
  },
  getters: {
  },
  actions: {
  },
  modules: {
  }
})

When referencing elsewhere, you only need to write the following code

import {INCREMENT, DECREMENT} from './store/mutations-type.js'
// . . . 
this.$store.commit(INCREMENT)
// . . . 
this.$store.commit(DECREMENT)
// . . . 

Network requests using Axios

index.js

// Import related modules
import axios from 'axios'


axios({
  	// This address can be used for network testing
  	url: 'http://httpbin.org'
    // By default, it is a get request. You can modify the request method by setting the value of method
    method: 'get'
    // The parameters passed in are specified through the params attribute
    params: {
    	name: xiaoming,
    	age: 18
	}
   	// Because axios supports Promise, Promise can be used to receive data
}).then(res => {
  	console.log(res)
})

axios sends concurrent requests

import axios from 'axios'

// This method returns all the requested results, puts the results into an array, and gets results in then. The object is an array
axios.all([axios({
    // Set base address
    baseURL: 'http://httpbin.org'
    url: '/home'
}), axios({
    url: 'http://httpbin.org'
})]).then(results => {
    console.log(results)
})

axios.all([axios({
    url: 'http://httpbin.org'
}), axios({
    url: 'http://httpbin.org'
})]).then(axios.spread((res1, res2) => {	// Via Axios The spread method can segment the obtained results
    console.log(res1)
    console.log(res2)
}))

Global configuration of axios

import axios from 'axios'

axios.default.baseURL = "http://httpbin.org"
// Sets the timeout in milliseconds
axios.timeOut = 50000

axios instance

import axios from 'axios'

const instance1 = axios.create({
    baseURL: 'http://httpbin.org',
    timeout: 5000
})

const instance2 = axios.create({
    baseURL: 'http://baidu.com',
    timeout: 3000,
    headers: {
        
    }
})

instance1({
    url: '/home',
    params: {
        name: xiaoming
    }
}).then(res => {
    console.log(res)
})

instance2({
    url: '/category',
    params: {
        name: xiaoming,
        age: 18
    }
}).then(res => {
    console.log(res)
})

Modular network request

When designing the network request module, it is best to write the network request to a separate file, so that when the network request framework is not maintained, it is easy to replace other frameworks

Create a separate folder: network, and create request JS file

request.js

import axios from 'axios'

// Mode 1:
export function request(config, success, failure) {
    const instance = axios.create({
        baseURL: 'http://baidu.com',
        timeout: 5000
    })
    
    instance(config).then(res => {
        success(res)
    }).catch(err => {
        failure(err)
    })
}

// Mode 2:
export function request(config) {
    const instance = axios.create({
        baseURL: 'http://baidu.com',
        timeout: 5000
    })
    
    instance(config.baseConfig).then(res => {
        config.success(res)
    }).catch(err => {
        config.failure(err)
    })
}

// Mode 3:
export function request(config) {
    return new Promise((resolve, reject) => {
        const instance = axios.create({
            baseURL: 'http://baidu.com',
            timeout: 5000
        })

        instance(config).then(res => {
            resolve(res)
        }).catch(err => {
            reject(err)
        })
    })
}

// Mode 4:
export function request(config) {
    const instance = axios.create({
        baseURL: 'http://baidu.com',
        timeout: 5000
    })

    return instance(config)
}

When using this module:

import { request } from './network/request.js'

// Corresponding mode I
request({
    url: '/home'
}, res=> {
    console.log(res)
}, err => {
    console.log(err)
})

// Corresponding mode 2
request({
    baseConfig: {
        url: '/home'
    },
    success: function(res) {
        console.log(res)
    },
    failure: function(err) {
        console.log(err)
    }
})

// Corresponding modes 3 and 4
request({
    url: '/home'
}).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

axios interceptor

import axios from 'axios'

export function request(config) {
    return new Promise((resolve, reject) => {
        const instance = axios.create({
            baseURL: 'http://baidu.com',
            timeout: 5000
        })
        
        // request interceptor 
        instance.interceptors.request.use(config => {
            // When you need to modify the configuration information, you can use the interceptor to modify it. When the user requests network data, you can add a response animation. When the user logs in, you can jump to the page without a token
            // This function returns configuration information
            console.log(config)
            // When the return configuration information is missing, the address will not be requested successfully, that is, the information is intercepted. But it did not continue down
            return config
        }, err => {
            // This function returns an error message
            console.log(err)
        })
        
        // Response interceptor
        instance.interceptors.response.use(res => {
            // The parameters passed in by this method are the results returned after the request
            console.log(res)
            // After modification, the response information needs to return the data, otherwise the information will not be received elsewhere
            return res.data
        }, err => {
            // This function is called when the request fails
            console.log(err)
        })

        return instance(config)
    })
}

nce(config).then(res => {
success(res)
}).catch(err => {
failure(err)
})
}

//Mode 2:
export function request(config) {
const instance = axios.create({
baseURL: 'http://baidu.com',
timeout: 5000
})

instance(config.baseConfig).then(res => {
    config.success(res)
}).catch(err => {
    config.failure(err)
})

}

//Mode 3:
export function request(config) {
return new Promise((resolve, reject) => {
const instance = axios.create({
baseURL: 'http://baidu.com',
timeout: 5000
})

    instance(config).then(res => {
        resolve(res)
    }).catch(err => {
        reject(err)
    })
})

}

//Mode 4:
export function request(config) {
const instance = axios.create({
baseURL: 'http://baidu.com',
timeout: 5000
})

return instance(config)

}

When using this module:

```js
import { request } from './network/request.js'

// Corresponding mode I
request({
    url: '/home'
}, res=> {
    console.log(res)
}, err => {
    console.log(err)
})

// Corresponding mode 2
request({
    baseConfig: {
        url: '/home'
    },
    success: function(res) {
        console.log(res)
    },
    failure: function(err) {
        console.log(err)
    }
})

// Corresponding modes 3 and 4
request({
    url: '/home'
}).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

axios interceptor

import axios from 'axios'

export function request(config) {
    return new Promise((resolve, reject) => {
        const instance = axios.create({
            baseURL: 'http://baidu.com',
            timeout: 5000
        })
        
        // request interceptor 
        instance.interceptors.request.use(config => {
            // When you need to modify the configuration information, you can use the interceptor to modify it. When the user requests network data, you can add a response animation. When the user logs in, you can jump to the page without a token
            // This function returns configuration information
            console.log(config)
            // When the return configuration information is missing, the address will not be requested successfully, that is, the information is intercepted. But it did not continue down
            return config
        }, err => {
            // This function returns an error message
            console.log(err)
        })
        
        // Response interceptor
        instance.interceptors.response.use(res => {
            // The parameters passed in by this method are the results returned after the request
            console.log(res)
            // After modification, the response information needs to return the data, otherwise the information will not be received elsewhere
            return res.data
        }, err => {
            // This function is called when the request fails
            console.log(err)
        })

        return instance(config)
    })
}

Keywords: Javascript npm Vue.js Webpack

Added by mobtex on Mon, 17 Jan 2022 22:26:20 +0200