vue official website:https://cn.vuejs.org/
Origin of framework
Core idea
There are some methods inside Vue. Those with $ at the beginning are some practical methods and attributes. We can configure the code to enter. This process is called injection. Those with _ at the beginning are members used internally by Vue. Developers should not use them.
var vm = new Vue({
el: "#app",
data: {
products: [
{ name: "iphone", stock: 10 },
{ name: "xiaomi", stock: 9 },
{ name: 'huawei', stock: 8 },
]
},
computed: {
total() {
return this.products.reduce((a, b) => a + b.stock, 0);
}
},
methods: {
changeStock(products, newStock) {
if (newStock < 0) {
newStock = 0;
}
products.stock = newStock//数据变化
},
remove(index) {
this.products.splice(index, 1);
}
},
})
injection:
vue will inject the following configuration into the vue instance:
- data: data related to the interface
- computed: data calculated from existing data, which will be explained in detail in the future
- methods: methods
You can use members in the vue instance in the template, but they must be placed in the bearded syntax { { }}
Enter vm in the console (vm is defined as the vue object above) and you can see the instance object of vue.
After the injection is completed, the data will be responsive, that is, if the data in the data changes, it will affect the interface.
Virtual DOM tree
Directly operating the real DOM will seriously affect efficiency and trigger browser reflow and reflow. VUE uses virtual dom (vnode) to describe the content to be rendered. vnode is an ordinary js object used to describe what should be on the interface. What.
The vue template is not a real dom, it will be compiled into a virtual dom
<div id="app">
<h1>标题:商品管理系统</h1>
<ul>
<li v-for="(item, i) in products">
商品名称:{
{item.name}}
<button @click="changeStock(item,item.stock-1)">-</button>
{
{item.stock?item.stock:"无货"}}
<button @click="changeStock(item,item.stock+1)">+</button>
<button @click="remove(i)">删除</button>
</li>
</ul>
<p>总库存:{
{total}}</p>
</div>
These contents will be compiled into virtual dom
During the compilation process, the label is used as a node, and then the content can be changed
When the data changes, re-rendering will be triggered. Vue will compare the differences between the old and new trees and apply the differences to the real dom tree.
vue generates vnode tree through the following logic
It is generated through the vue instance method render. If there is no render method, the template (temple) is used to compile the content into a vnode tree. If there is no handwritten template, the outerHTML configured by el is used as the template.
The number of virtual nodes must be single-rooted. If not, only the first one will be recognized.
mount
Putting the generated real DOM tree at the position of a certain element is called mounting.
1. Configure through el:css selector
2. Configure through vue instance.$mount('css selector")
The instance is created ->injection-> (compile to generate virtual node tree ->mount) (when rendering for the first time) ->mounted.
If the data changes after mounting, the page will respond and be re-rendered as above.
Little knowledge: v-bind: determined to define the image position
<div id="app">
<img :src="image" alt="" />
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
data: {
image:
"https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2342083191,4139347491&fm=26&gp=0.jpg",
},
});
vm.$mount("#app");
</script>
v-for: loop array; pay attention to binding the key value, the key value is unique and stable
<!-- vue模板 -->
<div id="app">
<h1>系统名称:{
{title}}</h1>
<ul>
<li v-for="(item, i) in products" :key="item.id">
{
{item.name}}
<button @click="changeStock(item, item.stock-1)">-</button>
<span>{
{item.stock > 0 ? item.stock : "无货"}}</span>
<button @click="item.stock++">+</button>
<button @click="deleteProduct(i)">删除</button>
</li>
</ul>
<p>总库存:{
{totalStock}}</p>
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
// 配置对象
el: "#app",
data: {
title: "库存管理系统",
products: [
{ id: 1, name: "iphone", stock: 0 },
{ id: 2, name: "xiaomi", stock: 6 },
{ id: 3, name: "huawei", stock: 7 },
],
},
computed: {
totalStock() {
return this.products.reduce((a, b) => a + b.stock, 0);
},
},
methods: {
deleteProduct(i) {
this.products.splice(i, 1);
},
changeStock(p, newStock) {
if (newStock < 0) {
newStock = 0;
}
p.stock = newStock;
},
},
});
v-on: can be abbreviated as @:variate
How to reduce complexity and reduce repetitive problems:
It is mainly solved by components. There are two main purposes for components:
1. Reduce the overall complexity and improve the readability and maintainability of the code
2. Improve the reusability of local code
In most cases, a component is a certain area on the page, and the component contains the
To include styles in components requires support from build tools
Component development
Create component
Components are created based on a common configuration object, so to develop a component, you only need to write a configuration object.
The configuration object and the configuration of the vue instance arealmost the same
//Component configuration object
It is worth noting that the component configuration object and the vue instance have the following differences:
- 无el
- data must be a function that returns an object as data
- there is no reason for thiselplacement, configuration of fiction DOM 树 Must be determined theretemplate orrendermedium
Register component
There are two ways to register components, one isglobal registration, and the other islocal Register
Global registration
Once a component is globally registered, it can be used anywhere in the entire application.
The global registration method is:
// Parameter 1: Component name, this name will be used when using the component in the template in the future
// Parameter 2: component configuration object
//After this code is run, the component can be used in the template
Vue.component('my-comp', myComp)
In the template, you can use the component
But in some large-scale engineering projects, many components do not need to be used globally. For example, a login component can only be used in login-related pages. If it is registered globally, the build tool will not be able to optimize the packagingTherefore, unless the component is particularly versatile, it is not recommended to use global registration
partial registration
Local registration means registering components wherever they are needed;
The way to register locally is to add a configuration to the component or instance where the component is to be used:
Build// This is another component that uses my-comp
//The attribute name is the component name, which will be used in the template
//The attribute value is the component configuration object
<!-- Other contents of this component -->
application components
Using components in templates is very simple, just use the component name as the HTML element name.
But please pay attention to the following points:
Components can end themselves or end with an end tag, but there must be an end.
The following component usage is incorrect:
No matter which method you use to register a component, the naming of the component needs to follow the convention.
Components can usekebab-case dash nomenclature, or they can usePascalCase big camel case Nomenclature
Both of the following naming options are possible:
"my-comp": myComp, // Method 1
In fact, it can also be identified using the camelCase nomenclature camelCase, but it does not meet the official requirements
UsingPascalCase has the additional benefit of using two component names in the template
Therefore, when using components, for convenience, the following code is often used:
var MyComp = { //Component configuration } var OtherComp = { components:{ MyComp // ES6 shorthand properties } }
Construction project
VIEW-CLI
vue-cli is a scaffolding tool used to buildvueprojects
It uses webpack internally and has many preset plug-ins (plugin ) and loader (loader) to achieve out-of-the-box performance
In addition to basic plug-ins and loaders, vue-cli also comes with:
SFC
Single File Component, that is, one file contains all the code required for a component
<template> <!-- component template code --> </template>
<script> export default { // Component configuration } </script>
<style> /* Component style */ </style>
Precompiled
Whenvue-cli performs packaging, it will Directly convert the template in the component into therender function. This is called template pre-compilation
The advantages of doing this are:
- It is no longer necessary to compile templates during runtime, which improves operating efficiency.
- The compiled code of Vue is no longer needed in the packaging results, reducing the packaging volume.
In app.vue, the template should be written outside the script tag to facilitate pre-compilation into render. Otherwise, the packaging result cannot be compiled and the packaging volume will be increased.
Computed properties
Interview question: What is the difference between computed properties and methods?
Computed properties are essentially methods that contain getters and setters. When getting a calculated property, you are actually calling the getter method of the calculated property. Vue will collect the dependencies of calculated properties and cache the return results of calculated properties. The calculation will only be recalculated if dependencies change. Methods are not cached and each call to the method results in re-execution.
The getter and setter parameters of computed properties are fixed, getter has no parameters, and setter has only one parameter. The parameters of the method are not limited.
Due to the above differences, calculated attributes usually obtain other data based on existing data, and it is not recommended to use side effects such as asynchronous, current time, and random numbers in the process of obtaining data. (Only when responsive data changes, you will be notified) In fact, the most important difference between them is the difference in meaning. Computed properties are also data in meaning, which can be read or assigned; methods are operations in meaning, used to process some things.
Complete method of writing computed properties
computed: { propName(){ // getter } }
When the scoped attribute is added to the style module in app.vue, the root element of the child component will be affected by the class style of the parent component, and the child component has its own class style.
Component events
v-if 和 v-show
Interview question: What is the difference between v-if and v-show?
v-if can control whether to generate vnode, which indirectly controls whether to generate the corresponding dom. When v-if is true, the corresponding vnode will be generated and the corresponding dom element will be generated; when it is false, the corresponding vnode will not be generated, and naturally no dom element will be generated.
v-show will always generate vnode, which indirectly leads to always generating dom. It only controls the display attribute of the dom. When v-show is true, no processing is performed; when it is false, the display attribute of the generated dom is none.
Using v-if can effectively reduce the tree's nodes and rendering amount, but it will also cause the tree to become unstable; while using v-show can keep the tree stable, but it cannot reduce the tree's nodes and rendering amount. Therefore, in actual development, v-show should be used when the display status changes frequently to maintain the stability of the tree; v-if should be used when the display status changes rarely to reduce the number of tree nodes and rendering volume.
Component events
Throwing an event: Something happens to the child component at a certain time, but it cannot handle it by itself, so it notifies the parent component to handle it through an event.
Event parameters: data passed to the parent component when the child component throws an event
Register event: The parent component declares that when something happens to the child component, it will do some processing.
Optimize engineering structure
How to use components
How to test component effects
slot
Simple usage
<!-- message component: a pop-up message -->
<div class="message-container">
<!-- slot is a built-in component of vue -->
Built-in components, slots, placeholders
<div class="message-container">
The content in the Message tag of the parent component will replace the position occupied by the slot tag in the message component.
named slot
If a component requires the parent element to pass the content of multiple areas, it means that multiple slots need to be provided.
In order to avoid conflicts, different slots need to be given different names.
<div class="layout-container">
<!-- We want to put the header here and provide a slot called header -->
<!-- We want to put the main content here and provide a slot named default -->
<!-- We want to put the footer here and provide a slot called footer -->
<h1>Here might be a page title</h1>
<p>A paragraph for the main content.</p>
<p>Here's some contact info</p>
v-slot:name to define where to send the slot
If it is the default value, you don’t need to write the template tag.
routing
Routing plug-in
import VueRouter from 'vue-router'
Vue.use(VueRouter); // Vue.use(plug-in) installs the plug-in in Vue
const router = new VueRouter({
Basic use
const router = new VueRouter({
//When the path /foo is matched, render the Foo component
{ path: '/foo', component: Foo },
//When the path /bar is matched, render the Bar component
{ path: '/bar', component: Bar }
<!-- The components matched by vue-router will be rendered here -->
navigation
vue-router provides the global component RouterLink, its rendering result is an a element
<RouterLink to="/blog">文章</RouterLink>
<!-- mode:history generation -->
<!-- To avoid refreshing the page, vue-router actually adds a click event to it and prevents the default behavior, using the hitory api inside the event to change the path -->
active state
Under the circumstances,vue-routerFor the meetingCurrent road diameter Fish allocation Train route diameter :
- If the current path starts with the navigation path, it is counted as a match, and the class name will be added to the navigation a elementrouter-link-active
- If the current path is exactly equal to the navigation path, it is counted as an exact match and the class name will be added to the navigation a elementrouter-link-exact-active
- For example, if the currently accessed path is /blog, then:
/blog router-link-active router-link-exact-active
You can add the bool attribute exact to the component RouterLink and change the matching rule to: Exact matching is required to add the matching class name router-link-active.
For example, if the currently accessed path is /blog, then:
Navigation path exact class name
/blog false router-link-active router-link-exact-active
For example, if the currently accessed path is /blog/detail/123, then:
Navigation path exact class name
/blog false router-link-active
In addition, the matching class name can be changed through the active-class attribute, and the exact matching class name can be changed through exact-active-class
named route
Use named routes to decouple systems from paths
const router = new VueRouter({
//When the path /foo is matched, render the Foo component
{ name:"foo", path: '/foo', component: Foo },
//When the path /bar is matched, render the Bar component
{ name:"bar", path: '/bar', component: Bar }
<!-- Pass the routing information object to the to attribute. RouterLink will generate the corresponding path based on the information you pass and the routing configuration -->
<RouterLink :to="{ name:'foo' }">go to foo</RouterLink>
dynamic routing
We hope that the following addresses can matchBlogcomponent
- /article, show all articles
- /article/cate/1,Show categoryid为1 sentences
- /article/cate/3,Show categoryid为3 sentences
- ...
The first case is very simple, you only need to match a fixed address to theBlog component
{ path: "/article", name: "Blog", component: Blog }
But the following situation is different: part of the address matching the Blog component changes dynamically, so you need to use a Special expressions:
{ path: "/article/cate/:categoryId", name: "CategoryBlog", component: Blog }
Use:xxx in the address to express that the content of this part changes. In In vue-router, call this part of the change params, which can be found in vueThe component is obtained throughthis.$route.params
// 访问 /article/cate/3 this.$route.params // { categoryId: "3" }
// 访问 /article/cate/1 this.$route.params // { categoryId: "1" }
Dynamic routing navigation
<router-link to="/article/cate/3">to article of category 3</router-link>
}">to article of category 3</router-link>
Programmatic navigation
In addition to using <RouterLink> hyperlink navigation, vue-router also allows page jumps in code
this.$router.push("Jump address"); // Ordinary jump
this.$router.push({ // Named route jump
this.$router.go(-1); // Fallback. Similar to history.go
watch
Using watch configuration, you can directly observe changes in certain data, and do some processing when changes occur.
// Observe the change of this.$route. After the change, the function will be called
// newVal: the new value of this.$route, equivalent to this.$route
// oldVal: this.$route old value
deep: false, // Whether to monitor changes in the internal attributes of the data, default false
immediate: false // Whether to execute the handler immediately, default false
// Observe the change of this.$route.params. After the change, the function will be called
["$route.params"](newVal, oldVal){
// newVal: the new value of this.$route.params, equivalent to this.$route.params
// oldVal: this.$route.params old value
deep: false, // Whether to monitor changes in the internal attributes of the data, default false
immediate: false // Whether to execute the handler immediately, default false
popup message
Use css module
You need to name the style filexxx.module.ooo
ooo为样style sentence after name, it is possiblecss, less
Get the Dom rendered by the component
Get the Dom root element rendered by a component
function getComponentRootDom(comp, props){
Extend vue instance
The properties added on Vue.prototype can be used in both component instances and Vue constructors.
Vue.prototype.sayHello adds method on the prototype chain.
ref
<p ref="para">some paragraph</p>
<button @click="handleClick">View all quotes</button>
import ChildComp from "./ChildComp"
comp: component instance of ChildComp
You can directly operate DOM elements through ref, and you may even directly modify sub-components. These are not in line with the design concept of Vue.
Don't use ref unless absolutely necessary
Get remote data
vue cli: https://cli.vuejs.org/zh/
axios: https://github.com/axios/axios
mockjs:http://mockjs.com/
significance
The server maintains updated data from the background page, and the front page gets the latest data from the server.
The development environment has cross-domain issues
There are no cross-domain issues in the production environment
Solve cross-domain issues in development environments
Why Mock data is needed
Component life cycle
The instance is created ->injection->compile and generate a virtual DOM tree->mounted->mounted (if the data changes, responsive rendering, regenerate the virtual DOM tree and compare the differences, and apply the differences to the real dom)->Complete rendering
life cycle hook function
beforeCreate();created();beforeMount();mounted();beforeUpdate();updated();
Load remote data
Directly operate dom
this.containerWidth = this.$refs.container.clientWidth;
this.containerHeight = this.$refs.container.containerHeight;
Start and clear timers
this.timer = setInterval(()=>{
Custom instructions
define directive
//The command name is: mydirec1
//The command name is: mydirec2
After that, all components can use the mydirec1 and mydirec2 instructions
<!-- A certain component code -->
<MyComp v-mydirec1="js expression" />
<div v-mydirec2="js expression">
<img v-mydirec1="js expression" />
Local definition refers to defining instructions in a component, which is similar to locally registered components.
The defined directive is only valid within this component.
<!-- A certain component code -->
<MyComp v-mydirec1="js expression" />
<div v-mydirec2="js expression">
<img v-mydirec1="js expression" />
Like local registration components, in order to make instructions more versatile, we usually extract the configuration of instructions to other modules.
<!-- A certain component code -->
<MyComp v-mydirec1="js expression" />
<div v-mydirec2="js expression">
<img v-mydirec1="js expression" />
//Import the instruction configuration object needed for the current component
import mydirec1 from "@/directives/mydirec1";
import mydirec2 from "@/directives/mydirec2";
directive configuration object
Directives without configuration, like components without configuration, are meaningless
Vue supports configuring some hook functions in instructions. At the appropriate time, Vue will call these hook functions and pass in appropriate parameters so that developers can complete what they want to do.
//Command configuration object
// Only called once, when the directive is bound to an element for the first time. One-time initialization settings can be performed here.
// Called when the bound element is inserted into the parent node.
// Called when the VNode of the component is updated
When each hook function is called, Vue will pass it some parameters, the most important of which are the first two parameters.
//Command configuration object
// el is the real DOM corresponding to the bound element
// binding is an object that describes the information provided in the instruction
binding object
binding: An object containing the following properties:
- name: Directive name, inclusive v- Preface.
- value: The binding value of the directive, for example: v-my-directive="1 + 1"< In a i=3>, the binding value is 2.
Simplified configuration
Most of the time, when configuring custom instructions, we will configure two hook functions
In this way, the hook function can be run when the element is bound and updated.
If these two hook functions implement the same function, you can directly simplify the instruction configuration into a separate function:
// This function will be set to both bind and update
Component mix-ins
// Extracted common code const common = { data(){ return { a: 1, b: 2 }},created(){ console.log("common created");},computed:{ sum() { return this.a + this.b; } }}
- Using comp1, you will get:
- common created
- comp1 created 1 2 3*/const comp1 = {mixins: [common] // The reason why it is an array is because multiple configuration codes can be mixed in created(){console.log("comp1 created", this.a, this .b, this.sum);}}
Component communication
props
Property transfer from parent component to child component; generally used with v-for, which loops the content within the property. The constraint type "type" can be set; the default value is "default:...", and subcomponents have no right to change.
event
Child component throws event to parent component
Use vue instance method, $emit();
$refs
Directly obtain a component, that is, the parent component directly obtains the reference of the child component
router
Communicate between different components indirectly through routing
$listeners
Get all event functions passed from the parent component
v-model
v-model is a syntactic sugar, which is a combination of value attribute and input event.
event bus
Component communication can be maintained without any introduction and introduction relationship between the two pages.
Article data logic
There is a background page, one of which is to add articles or edit articles, and let us write markdown. The background page also has some functions, which can convert markdown to html. We also have to extract the markdown directory to form a TOC array;
Submit the markdown and html code and TOC array to the server, and the server will return the html and toc to the front page for display.
BlogDetail
There is no difficulty in this component, just display the article information according to "Properties - Article Object"
Since the content of the article belongs tooriginal html, you need to use v-html command to set
In addition, the content of the article is not styled, so you need to choose a markdown css style (see attachmentmarkdown.css)
For the styles of the script part in the article, you can use the styles provided by the third-party libraryhighlight.js
import "highlight.js/styles/github.css";
event modifier
Native events fordom nodes, vue< /span>Supports multiple modifiers to simplify code
For details, see:Event modifiers, key modifiers, system modifiers
$listeners
$listeners is an instance property ofvue, which is used to obtain the information passed by the parent component. All event functions
<!-- Parent component --> <Child @event1="handleEvent1" @event2="handleEvent2" />
// Subcomponent this.$listeners // { event1: handleEvent1, event2: handleEvent2 }
$emit和$listenersCommunication difference
Similarity: Both child components can pass messages to parent components.
- $emit is more consistent with one-way data flow. The child component only sends notifications and the parent component listens to make changes; And. is the method of directly using the parent component in the child component$listeners
- The debugging tool can listen to the event of the subcomponent$emit, but cannot listen to the event of $listeners Method call in . (Think about why)
- Since the passed method can be obtained from$listeners, calling the method can get its return value. But $emit only sends a notification to the parent component and cannot know the result of the parent component's processing
For the third point above, you can pass the callback function in$emit to solve
<Child @click="handleClick" />
console.log(data); // Get the data in the subcomponent event
callback(1); // After a period of time, call the callback function passed by the subcomponent
this.$emit("click", 123, (data)=>{
console.log(data); // data is the data obtained after the parent component completes processing
v-model
The v-model directive is essentially syntactic sugar, which is a combination of the value attribute and the input event.
<input :value="data" @input="data=$event.target.value" />
:value="data"Bind the value of the input box, @input="data=$event.target.value"Register event, change the data when the input content changes
data sharing
There will be some problems when encountering data sharing in vue.
If the data is not unique, a lot of memory resources will be wasted and operating efficiency will be reduced.
If the data is not unique, it will cause the data to be inconsistent and difficult to maintain.
If a component changes data, how to let other components that use the data know that the data has changed?
The event bus seems to be able to solve this problem, but it requires manual maintenance and monitoring in the component, which is extremely inconvenient. Moreover, the purpose of the event bus is to "notify" rather than "share data"
One solution that is easier to think of is to upgrade all shared data to the root component, and then continuously send it through attributes. When a component needs to modify the data, events will continue to be thrown upward until the root component completes the data processing. Revise.
The shortcomings of this solution are also very obvious:
- A lot of code needs to be written to deliver data layer by layer, and many components are forced to have data they don’t need at all.
- A lot of code needs to be written to throw events up layer by layer, and many components are forced to register events that they cannot handle at all.
Based on the above questions, we can simply set up an independent data warehouse.
- Whatever shared data a component needs can be freely obtained from the warehouse, and you can get whatever you need.
- Components can freely change the data in the warehouse. After the data in the warehouse changes, the components that use the corresponding data will be automatically notified to update.
To achieve all this, you can choosevuex
Create warehouse
After installationvuex, you can create a data warehouse through the following code. In most cases, a project only needs to create one data Warehouse
import Vuex from "vue"; import Vue from "vue"; Vue.use(Vuex);
// Apply vuex plug-in
const store = new Vuex.Store({
// Warehouse configuration
state: {
// The initial state of the warehouse (data)
count: 0 } })
export default store;
After the warehouse is created, you can usestore.state to access the data in the warehouse
If you want to conveniently use warehouse data invue, you need to vuex Install as a plug-in
// store.js
import Vuex from "vue";
import Vue from "vue";
Vue.use(Vuex); // Install Vuex plug-in
const store = new Vuex({
// Warehouse configuration
state: { // Initial state of the warehouse (data)
count: 0// main.jsexport default store;})
}import App from "./App.vue";import store from "./store .js";new Vue({ store, // Inject the warehouse into vue render: h => h(App)}).$ mount("#app");
After , in the vue component, you can pass the instance's $store< a i=4>Attribute access to warehouse
Vuex will automatically set the configured state data to responsive data. When the data changes, components that rely on the data will automatically render.
Data changes
Although data can be directly changed using the responsive nature of data, such an approach will encounter problems in large projects.
If one day you find that a certain shared data is wrong, and more than a hundred components may have changed this data, how do you know which data change step caused the problem?
In order to better track data changes, vuex is strongly recommended to use mutationto change data
const store = new Vuex({
// Warehouse configuration
state: { // Initial state of the warehouse (data)
count: 0 a> a>}) } } state.count **= payload; power(state, payload){ */ * In this mutation, we agree that the payload is a number, representing the exponent * The payload can be of any type, including numbers, strings, and objects. * We call the additional information when the data changes called load (load) payload * This mutation requires an additional parameter to provide the exponent * Find n Power /** }, state.count--; decrease(state){ }, state.count++; increase (state){ */ * The parameter state is the current warehouse data * The increase mutation describes the changes that should occur when the data is increased * Each mutation is a method, which describes the change of data in a certain scenario /** mutations: {
},
When we havemutation, we should not directly modify the data in the warehouse
Instead submit a mutationstore.commit method >, the specific method is
store.commit("name of mutation", payload);
Now, we can observe the changes in the data throughvue devtools
- Asynchronous operations are not allowed in mutationIn the actual development specifications, it is even required that no side-effect operations are allowed
Asynchronous processing
If you want to perform asynchronous operations in vuex, you need to use action
const store = new Vuex({
state: {
count: 0
},
mutations: {
increase(state){
state.count++;
},
decrease(state){
state.count--;
},
power(state, payload){
state.count **= payload;
}
},
actions: {
/**
* ctx: 类似于store的对象
* payload: 本次异步操作的额外信息
*/
asyncPower(ctx, payload){
setTimeout(function(){
ctx.commit("power", payload)
}, 1000)
}
}
})
User module logic diagram
Reference Fee
view
vuex
router
Packaging optimization
Analyze packaging results
Since vue-cli uses webpack for packaging, we only need to add a webpack plug-in webpack-bundle-analyzer to analyze the packaging results.
In order to avoid starting webpack-bundle-analyzer in the development environment, we can simply use the following code to create a webpack.config.js file
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
// Additional configuration of webpack can be performed through the configureWebpack option
// This configuration will eventually be merged with the default configuration of vue-cli (webpack-merge)
plugins: [new BundleAnalyzerPlugin()]
Optimize public library packaging volume
Use CDN
CDN stands for Content Delivery Network, which is called content distribution network.
Its basic principle is to set up multiple servers. These servers regularly take resources from the origin site and save them locally, so that users in different regions can obtain resources by accessing the nearest server.
We can put all the static resources in the project on CDN (for a fee), or we can use ready-made free CDN to obtain resources from public libraries.
First, we need to tellwebpacknot to package public libraries
Then, manually add the cdn link to the page, here use bootcn
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.5.1/vuex.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.4.7/vue-router.min.js"></script>
<!-- built files will be auto injected -->
Forvuex and vue-router, use this If introduced in a traditional way, it will automatically become a plug-in for Vue, so you need to remove Vue.use(xxx)< /span>
We can use the following code for compatibility
// There is no traditional way to introduce Vuex
import VueRouter from "vue-router";
// There is no traditional way to introduce VueRouter
Enable modern mode
In order to be compatible with various browsers, vue-cli is used internally@babel/present -envDowngrade the code, you can set the target browser that needs to be compatible through.browserlistrcconfiguration a>
This is a lazier approach because for those using modern browsers, they alsoForced to use downgraded code, and the downgraded code contains a large number ofpolyfill, Thus increasing the size of the package
Therefore, we want to provide two packaging results:
- Downgraded package (large), provided to users of old browsers
- Undowngraded package (small) for modern browser users
In addition to using webpack for multiple packaging, you can also use vue-cliCommands provided to us:
vue-cli-service build --modern
Optimize project package size
The project package here refers to the packaging result in the src directory
Page subcontracting
By default, vue-cli will utilize webpackPackage all the code in the src directory into a bundle
This means that when accessing a page, you need to load the jscode of all pages
We can take advantage ofwebpack's support fordynamic import , so as to package the codes of different pages into different files
component: () => import(/* webpackChunkName: "home" */ "@/views/Home"),
component: () => import(/* webpackChunkName: "about" */"@/views/About"),
Optimize first screen response
The white screen on the homepage is affected by many factors
The vue page needs to be built through js, so there is nothing on the page until the js is downloaded locally.
A very simple and effective method is to render a small loading effect in the page first, and wait until the js is downloaded locally and run, it will be automatically replaced.