vue2-getting started

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.

Mounting method:

1. Configure through el:css selector

2. Configure through vue instance.$mount('css selector")

Complete process

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

For example:

<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

For example:

<!-- 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

Binding events

Specify parameter event name

Abbreviation@

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

fine-grained partitioning

In most cases, a component is a certain area on the page, and the component contains the

Function (js code)

Content (template code)

Style (css code)

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

var myComp = {

 data(){

 return {

 // ...

 }

 },

 template: `....`

}

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

Two ways:

<my-comp /> <!-- or -->

<my-comp></my-comp>

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

var otherComp = {

 components:{

 //The attribute name is the component name, which will be used in the template

 //The attribute value is the component configuration object

 "my-comp": myComp

 },

 template: `

 <div>

 <!-- Other contents of this component -->

 <my-comp></my-comp>

 </div>

 `;

}

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:

  1. Component must have an end

Components can end themselves or end with an end tag, but there must be an end.

The following component usage is incorrect:

<my-comp>

  1. Component naming

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:

var otherComp = {

 components:{

 "my-comp": myComp, // Method 1

 MyComp: myComp //Method 2

 }

}

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

var otherComp = {

 components:{

 MyComp: myComp

 }

}

In the template:

<!--Available -->

<my-comp />

<MyComp />

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

vue Chinese official website:

Summary | Vue CLI

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:

  • babel
  • webpack-dev-server
  • eslint
  • postcss
  • less-loader

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:

  1. It is no longer necessary to compile templates during runtime, which improves operating efficiency.
  2. The compiled code of Vue is no longer needed in the packaging results, reducing the packaging volume.

Source code->Package->Run

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: {

 get(){

 // getter

 },

 set(val){

 // sets

 }

 }

}

abbreviation

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

Write component documentation

./src/components/README.md

How to test component effects

Rapid prototyping | Vue CLI

slot

Simple usage

<!-- message component: a pop-up message -->

<div class="message-container">

 <div class="content">

 <!-- slot is a built-in component of vue -->

Built-in components, slots, placeholders

 <slot></slot>

 </div>

 <button>OK</button>

 <button>Close</button>

</div>

<!-- Parent component App -->

<Message>

 <div class="app-message">

 <p>App Message</p>

 <a href="">detail</a>

 </div>

</Message>

<!--Final result -->

<div class="message-container">

 <div class="content">

 <div class="app-message">

 <p>App Message</p>

 <a href="">detail</a>

 </div>

 </div>

 <button>OK</button>

 <button>Close</button>

</div>

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.

<!-- Layout component -->

<div class="layout-container">

 <header>

 <!-- We want to put the header here and provide a slot called header -->

 <slot name="header"></slot>

 </header>

 <main>

 <!-- We want to put the main content here and provide a slot named default -->

 <slot></slot>

 </main>

 <footer>

 <!-- We want to put the footer here and provide a slot called footer -->

 <slot name="footer"></slot>

 </footer>

</div>

<!-- Parent component App -->

<BaseLayout>

 <template v-slot:header>

 <h1>Here might be a page title</h1>

 </template>

 <template v-slot:default>

 <p>A paragraph for the main content.</p>

 <p>And another one.</p>

 <template v-slot:default>

 

 <template v-slot:footer>

 <p>Here's some contact info</p>

 </template>

</BaseLayout>

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

npm i vue-router

Use of routing plug-ins

import Vue from 'vue'

import VueRouter from 'vue-router'

Vue.use(VueRouter); // Vue.use(plug-in) installs the plug-in in Vue

const router = new VueRouter({

 // Routing configuration

})

new View({

 ...,

 router

})

Basic use

//Route configuration

const router = new VueRouter({

 routes: [ // routing rules

 //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 }

 ]

})

<!-- App.vue -->

<div class="container">

 <div>

 <!--Public Areas -->

 </div>

 <div>

 <!-- Page area -->

 <!-- The components matched by vue-router will be rendered here -->

 <RouterView />

 </div>

</div>

navigation

vue-router provides the global component RouterLink, its rendering result is an a element

<RouterLink to="/blog">文章</RouterLink>

<!-- mode:hash generation -->

<a href="#/blog">文章</a>

<!-- 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 -->

<a href="/blog">文章</a>

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:

Navigation path class name

/ router-link-active

/blog router-link-active router-link-exact-active

/about none

/message None

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

/ true None

/blog false router-link-active router-link-exact-active

/about true none

/message true None

For example, if the currently accessed path is /blog/detail/123, then:

Navigation path exact class name

/ true None

/blog false router-link-active

/about true none

/message true None

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

//Route configuration

const router = new VueRouter({

 routes: [ // routing rules

 //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 categoryid1 sentences
  • /article/cate/3,Show categoryid3 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>

<router-link :to="{

 name: 'CategoryBlog',

 params: {

 categoryId: 3

 }

}">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

 name:"Blog"

})

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.

export default {

 // ... other configurations

 watch: {

 // Observe the change of this.$route. After the change, the function will be called

 $route(newVal, oldVal){

 // newVal: the new value of this.$route, equivalent to this.$route

 // oldVal: this.$route old value

 },

 // Complete writing method

 $route: {

 handler(newVal, oldVal){},

 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

 },

 // Complete writing method

 ["$route.params"]: {

 handler(newVal, oldVal){},

 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

xxx is the file name

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){

 const vm = new Vue({

 render: h => h(comp, {props})

 })

 vm.$mount();

 return vm.$el;

}

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

<template>

 <div>

 <p ref="para">some paragraph</p>

 <ChildComp ref="comp" />

 <button @click="handleClick">View all quotes</button>

 </div>

</template>

<script>

 import ChildComp from "./ChildComp"

 export default {

 components:{

 ChildComp

 },

 methods:{

 handleClick(){

 // Get all references held

 console.log(this.$refs);

 /*

 {

 para: p element (native DOM),

 comp: component instance of ChildComp

 }

 */

 }

 }

 }

</script>

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();

beforeDestroy();destroyed()

Load remote data

export default {

 data(){

 return {

 news: []

 }

 },

 async created(){

 this.news = await getNews();

 }

}

Directly operate dom

export default {

 data(){

 return {

 containerWidth:0,

 containerHeight:0

 }

 },

 mounted(){

 this.containerWidth = this.$refs.container.clientWidth;

 this.containerHeight = this.$refs.container.containerHeight;

 }

}

Start and clear timers

export default {

 data(){

 return {

 timer: null

 }

 },

 created(){

 this.timer = setInterval(()=>{

 ...

 }, 1000)

 },

 destroyed(){

 clearInterval(this.timer);

 }

}

Custom instructions

define directive

Global definition:

//The command name is: mydirec1

Vue.directive('mydirec1', {

 //Command configuration

})

//The command name is: mydirec2

Vue.directive('mydirec2', {

 //Command configuration

})

After that, all components can use the mydirec1 and mydirec2 instructions

<template>

 <!-- A certain component code -->

 <div>

 <MyComp v-mydirec1="js expression" />

 <div v-mydirec2="js expression">

 ...

 </div>

 <img v-mydirec1="js expression" />

 </div>

</template>

Local definition:

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.

<template>

 <!-- A certain component code -->

 <div>

 <MyComp v-mydirec1="js expression" />

 <div v-mydirec2="js expression">

 ...

 </div>

 <img v-mydirec1="js expression" />

 </div>

</template>

<script>

export default {

 //Define instructions

 directives: {

 //Command name: mydirec1

 mydirec1: {

 //Command configuration

 },

 //Command name: mydirec2

 mydirec2: {

 //Command configuration

 }

 }

}

</script>

Like local registration components, in order to make instructions more versatile, we usually extract the configuration of instructions to other modules.

<template>

 <!-- A certain component code -->

 <div>

 <MyComp v-mydirec1="js expression" />

 <div v-mydirec2="js expression">

 ...

 </div>

 <img v-mydirec1="js expression" />

 </div>

</template>

<script>

 //Import the instruction configuration object needed for the current component

 import mydirec1 from "@/directives/mydirec1";

 import mydirec2 from "@/directives/mydirec2";

 export default {

 //Define instructions

 directives: {

 mydirec1,

 mydirec2

 }

 }

</script>

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.

Commonly used hook functions:

//Command configuration object

{

 bind(){

 // Only called once, when the directive is bound to an element for the first time. One-time initialization settings can be performed here.

 },

 inserted(){

 // Called when the bound element is inserted into the parent node.

 },

 update(){

 // 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

{

 bind(el, binding){

 // 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

{

 bind(el, bingding){

 

 },

 update(el, bingding){

 

 }

}

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:

function(el, bingding){

 // 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.

Differences:

  • $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

Parent component:

<template>

 <Child @click="handleClick" />

</template>

<script>

 import Child from "./Child"

 export default {

 components:{

 Child

 },

 methods:{

 handleClick(data, callback){

 console.log(data); // Get the data in the subcomponent event

 setTimeout(()=>{

 callback(1); // After a period of time, call the callback function passed by the subcomponent

 }, 3000)

 }

 }

 }

</script>

Subassembly:

<template>

<button @click="handleClick">

 click

 </button>

</template>

<script>

 export default {

 methods:{

 handleClick(){

 this.$emit("click", 123, (data)=>{

 console.log(data); // data is the data obtained after the parent component completes processing

 })

 }

 }

 }

</script>

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

<!-- Equivalent to -->

<input v-model="data" />

data sharing

There will be some problems when encountering data sharing in vue.

How to keep data unique

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

**pay attention: **

  1. Asynchronous operations are not allowed in mutationIn the actual development specifications, it is even required that no side-effect operations are allowed

Side effects include:

    • asynchronous
    • Change or read information about the external environment, such aslocalStorage, location, DOM, etc.
  1. Commitmutationis the only reason why the data changed

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

watch configuration

Vue.prototype.$watch

vuex

mapState

getters

mapGetters

modules

watch

router

exact-path

Navigation front guard

navigation guard

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")

 .BundleAnalyzerPlugin;

// view.config.js

module.exports = {

 // 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)

 configureWebpack: {

 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

// view.config.js

module.exports = {

 configureWebpack: {

 externals: {

 vue: "Vue",

 vuex: "Vuex",

 "vue-router": "VueRouter",

 }

 },

};

Then, manually add the cdn link to the page, here use bootcn

<body>

 <div id="app"></div>

 <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 -->

</body>

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

// store.js

import Vue from "vue";

import Vuex from "vuex";

if(!window.Vuex){

 // There is no traditional way to introduce Vuex

 ​Vue.use(Vuex);

}

// router.js

import VueRouter from "vue-router";

import Vue from "vue";

if(!window.VueRouter){

 // There is no traditional way to introduce VueRouter

 Vue.use(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:

  1. Downgraded package (large), provided to users of old browsers
  2. 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

// routes

export default [

 {

 name: "Home",

 path: "/",

 component: () => import(/* webpackChunkName: "home" */ "@/views/Home"),

 },

 {

 name: "About",

 path: "/about",

 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.

<div id="app">

 <img src="loading.gif" />

</div>

Guess you like

Origin blog.csdn.net/Vince_13/article/details/132432968