Vue3: Basic Learning Notes

Click to jump to Vue.js Learning Reference Document

Introduction to vue3.0

What is Vue.js

1. Front End Development Framework
2. A progressive framework for building user interfaces
3. Simplify complex development processes
4. Vue is also fully capable of supporting complex single-page applications

install

There are four main ways to add Vue.js to a project:

1. Import it as a CDN package on the page

<script src="https://unpkg.com/vue@next"></script>

2. Download JavaScript files and host them yourself
If you want to avoid using a build tool but cannot use a CDN in production, you can download the associated.js file and host it using your own Web server. Then you can use

3. Install using npm
npm is the recommended installation method for building large applications with Vue

4. Build a project using the official CLI that provides battery-containing build settings for modern front-end workflows such as hot overload, lint-on-save, etc.
Vue provides the official CLI (Open New Window) to quickly build ambitious single-page applications

vite build tool tool to create vue3 project

Create with npm

Prerequisite: Install Node.js
The steps are as follows:

$  npm init vite@latest <project-name>  perhaps   $  npm init vite-app <project-name>

$ cd <project-name>
$ npm install
$ npm run dev

Using yarn

$ yarn create vite <project-name> --template vue
$ cd <project-name>
$ yarn
$ yarn dev

vue3 project structure

Binding Vue declarative syntax to data

Command

document.querySelector('h1').innerHTML="Baby Fan"

Declarative

export default {
  name: "App",
  data(){
    return{
      msg:'Xiao Fan'
    }
  },

  methods:{
    changeMsg(){
      this.msg = 'Xiao Fan Beauty'
    }
  }
};

Data Binding

Data changes, page content changes, page content changes, and data changes

    <h1 @click="changeMsg">{{msg}}</h1>
    <input type="text" v-model="msg"  />

Template syntax

Double Bracket Syntax

<h1>{{msg}}</h1>

v-once

One-time interpolation, rendering only once

 <!-- v-once Directive to render content only once -->
    <h1 @click="changeMsg" v-once>{{msg}}</h1>

v-html

Insert HTML code into content

 <!--v-html Instruction causes content to be inserted html Code  -->
    <div>{{content}}</div>
     <div v-html="content"></div>

v-bind

Content of the bound property

<!-- v-bind Contents of instruction-bound properties -->
 <div v-bind:id="id"></div>

Using JavaScript expressions in template syntax

<template>
  <div>
    <!-- JavaScript Can be used in template syntax -->
    <!-- Double Bracket Syntax -->
    <h1>{{ msg }}</h1>
    <!-- split()Division msg String, get a number -->
    <h1>{{msg.split('')}}</h1>
    <!-- reverse() Reverse the contents of the array -->
    <h1>{{msg.split('').reverse()}}</h1>
    <!-- join()Makes the array contents merge into strings -->
    <h1>{{msg.split('').reverse().join('')}}</h1>
    <!-- You can use ternary operators -->
    <div>{{color=="green"?"Happy":"Sorry"}}</div>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
      msg: "Hello,Word!",
      color:"green"
    };
  },
  methods: {
  },
};
</script>

Dynamic Instructions

Property names corresponding to instructions can be modified

<template>
  <div>
    <!-- Dynamic Instructions -->
    <div v-bind:[attrbuteName]="d1"></div>
    <button @click="toggleColor">Click to switch colors</button>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     attrbuteName:"class",
     d1:'d1'
    };
  },

  methods: {
    toggleColor() {
      this.attrbuteName = "id";
    },
  },
};
</script>

<style>
  #d1{
    margin-left: 47%;
    width: 100px;
    height: 100px;
    background-color: yellow;
  }
  .d1{
    margin-left: 47%;
    width: 100px;
    height: 100px;
    background-color: blue;
  }
</style>

Computing attributes

  • Simplify Code
<template>
  <div>
    <!-- Customary msg -->
    <h1>{{msg}}</h1>
    <!-- Application JS Statement inversion msg -->
    <h1>{{msg.split('').reverse().join('')}}</h1>
    <!-- Reverse using computed attributes msg -->
    <h1>{{reverseMsg}}</h1>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     msg: 'Hello World'
    };
  },
  computed:{
    reverseMsg(){
      return this.msg.split('').reverse().join('')
    }
  },

  methods: {
    toggleColor() {
      this.attrbuteName = "id";
    },
  },
};
</script>

watch listens for changes in data

To listen for changes in data, you can use watch to listen for a function that listens for the target variable. There are two parameters, the first is a new value and the second is an old value.

<template>
  <div>
    <!-- Customary msg -->
    <h1>{{msg}}</h1>
    <input type="text" v-model="msg">
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     msg: 'Hello World'
    };
  },
  
  watch:{
    msg(newValue,oldValue){
      if(newValue.length<10){
        alert("Too few values entered!!!")
      }

    }
  }
  
};
</script>

Multiple binding methods for classes

Place String

<template>
  <div>
    <!-- class class -->
    <!-- First, place the string -->
    <h1 v-bind:class = "msg">hello</h1>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     msg: 'Hello World'
    };
  },
};
</script>

Place Object

<template>
  <div>
    <!-- class class -->
   <!-- Place Object -->
   <h1 v-bind:class="{active:isActive}">Hello</h1>
   <button @click="toggleActive">Switch Styles</button>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     isActive: true
    };
  },

  methods:{
    toggleActive(){
      this.isActive=!this.isActive
    }
  }
  
  
};
</script>
<style scoped>
  .active{
    background-color: yellow;
  }
</style>

Place Array

<template>
  <div>
    <!-- class class -->
   <!-- Place Array -->
   <h1 :class="arr">Hello</h1>
   <button  @click="toggleActive">Switch Class</button>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     arr: ['swiper','active']
    };
  },

  methods:{
    toggleActive(){
      this.arr.pop()
    }
  }
};
</script>

Combination of Array and Object

<template>
  <div>
    <!-- class class -->
    <!-- Combination of Array and Object -->
    <h1 :class="[className, {active:isActive}]">Hello</h1>
    <button @click="toggleActive">Switch Class</button>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     className : "abc",
     isActive : true
    };
  },

  methods:{
    toggleActive(){
      this.className= "cba",
      this.isActive = !this.isActive
    }
  }
  
  
};
</script>
<style scoped>
.active {
  background-color: yellow;
}
</style>


Multiple binding methods for Style styles

Place String

<template>
  <div>
    <!-- class class -->
    <!-- First: Place a string -->
    <h1 :style="msg">Hello</h1>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     msg: "background:red;"
    };
  },
};
</script>

Place Object

<template>
  <div>
    <!-- class class -->
    <!-- First: Place a string -->
    <h1 :style="{background: 'purple'}">Hello</h1>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
     
    };
  },
};
</script>

Place Array

<template>
  <div>
    <!-- class class -->
    <!-- First: Place a string -->
    <h1 :style="[styleObj,{boxSizing: 'border-box'}]">Hello</h1>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
      styleObj:{
        background: "pink",
        border: '1px solid blue'
      }
     
    };
  },
};
</script>

v-if and v-show

  • v-if... v-else-if... v-else... can display multiple content according to different conditions, which consumes performance if switching frequently

  • v-show is conditionally determined whether to display a single content, but when not, it actually changes the style to display: none, which results in less performance consumption

<template>
  <div>
    <!-- Set up multiple content switching display -->
   <h1 v-if = "user == 'super VIP'"> Welcome Dad Golden</h1>
   <h1 v-else>Charging Makes You Stronger</h1>
   <button @click="toggleUser">Switch Users</button>

   <!-- Set up a content switching display -->
    <h1 v-show="isShow">Show me only one</h1>
    <button @click="toggleShow">switch</button>

  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
      user:'super VIP',
      isShow: true
    };
  },

  methods:{
    toggleUser(){
      this.user = "Ordinary user"
    },
    toggleShow:function(){
      this.isShow = !this.isShow
    }
  }
};
</script>

v-for cycle

  • Loop Array
  • Objects in Loop Array
  • Loop Object
<template>
  <div>
    <!-- Loop Array -->
    <ol>
      <li v-for="(item, i) in news" :key="i">{{ item }}====>{{ i }}</li>
    </ol>
    <!-- Objects in Loop Array -->
    <ol>
      <li v-for="(item, i) in news1" :key="i">
        {{ item.title }}==>{{ item.content }}===>{{ item.athor }}====>{{ i }}
      </li>
    </ol>
    <!-- Loop Object -->
    <ol>
      <li v-for="(item, i) in athor" :key="i">{{ item }}====>{{ i }}</li>
    </ol>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
      news: ["11111", "222222", "333333"],
       news1: [
      {
        title: "I'm Heading 1",
        content: "I am Content 1",
        athor: "Author 1",
      },
      {
        title: "I'm Heading 2",
        content: "I am Content 2",
        athor: "Author 2",
      },
    ],
    athor:{
      name:'lingLing',
      age: '18'
    }
    }
   
  },
};
</script>

Events and parameters, time modifiers

Binding events use v-on (abbreviated @)

  • Binding events do not require parameters
<h1 @click="addEvent">{{num}}</h1>
  • Bind events, handle expressions directly
 <h1 @click="num += 2">{{num}}</h1>
  • Bind events, pass parameters
 <h1 @click=" addEvent1(20)">{{num}}</h1>
  • Bind event. Pass $event event object and parameters
<h1 @click=" addEvent1(20,$event)">{{num}}</h1>
  • One event binds multiple handlers
 <h1 :style="{background:color}" @click="addEvent1(20,$event),changeColor($event)">{{num}}</h1>

Event modifier

  • Prevent event bubbles.stop
  • Block default events.prevent
  • Events are triggered only once.
<h1 @click.once=" addEvent1(20,$event)">{{num}}</h1>  

Key modifier

enter/tap.delete/esc/space/up/down/left/right

 <input type="text" @keydown.enter="searchEvent">

System Modifier

.ctrl/.alt/.shift/.meta

Mouse modifier

.left/.right/.middle
<template>
  <div>
    <!-- Bind events, no parameters required -->
    <h1 @click="addEvent">{{num}}</h1>
    <!-- Bind events, handle expressions directly -->
    <h1 @click="num += 2">{{num}}</h1>

    <!-- Bind events, pass parameters -->
    <h1 @click=" addEvent1(20)">{{num}}</h1>
    <!--Bind event. transmit $event Event objects and parameters -->
    <h1 @click=" addEvent1(20,$event)">{{num}}</h1>  

    <!-- One event binds multiple handlers -->
    <h1 :style="{background:color}" @click="addEvent1(20,$event),changeColor($event)">{{num}}</h1>

    <!-- Event modifier -->
    <!-- 
      Prevent Event Bubbles .stop
      Block default events .prevent
      Events are triggered only once .once
     -->
    <h1 @click.once=" addEvent1(20,$event)">{{num}}</h1>  
    
    <!-- Key modifier
    enter/tap.delete/esc/space/up/down/left/right
    System Modifier
    .ctrl/.alt/.shift/.meta
    Mouse modifier
    .left/.right/.middle
     -->
    <input type="text" @keydown.enter="searchEvent">
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
      num:0,
      color: 'red'
    }
  },
  methods:{
     addEvent:function(e){
       console.log(e)
       this.num += 2
     },

     addEvent1:function(number){
       this.num += number
     },

      addEvent2:function(number,event){
       this.num += number
     },

     changeColor:function(){
       this.color = 'pink'
     },
     searchEvent:function(){
       console.log("Search event executed!!!")
     }
   }
};
</script>
 

Form Input Binding, Modifier

Text box text

*Two-way binding of single-line text box data

<input v-model="searchKey" type="text" @keydown="searchEvent" />

textarea multiline text box

  • Data binding for multiline text boxes
<textarea v-model="lineText" name="textarea"  id="" cols="30" rows="10"></textarea>

Check box checkbox

  • Checkbox data binding, get whether the content is selected
<input type="checkbox" name="likes" v-model="fruits" value="Persimmon">
    <input type="checkbox" name="likes" v-model="fruits" value="Banana">
    <input type="checkbox" name="likes" v-model="fruits" value="Grape">
    <input type="checkbox" name="likes" v-model="fruits" value="Apple">

Radio radio

Only one value can be selected

<input type="radio" name="sex" value="man" v-model="picked">
<input type="radio" name="sex" value="woman" v-model="picked">

Option Box select

Adding a multiple attribute allows you to select multiple options

<select name="citys"  v-model="citys" multiple >
      <option value="Guangzhou"></option>
      <option value="Shanghai"></option>
      <option value="Beijing"></option>
      <option value="Chengdu"></option>
    </select>

Modifier for data binding v-model

.lazy

input changes to change event value, focus is out of focus before changing

<input v-model.lazy="searchKey1" type="text" @keydown="searchEvent" />

.number

Convert input values to numeric types

<input v-model.lazy.number="searchKey2" type="text" @keydown="searchEvent" />

.trim

Remove whitespace

 <input v-model.lazy.trim="searchKey3" type="text" @keydown="searchEvent" />

Case Code

<template>
  <div>
    <!-- Two-way binding of single-line text box data -->
    <input v-model="searchKey" type="text" @keydown="searchEvent" />
    <h1>{{ searchKey }}</h1>

    <!-- Data binding for multiline text boxes -->
    <textarea v-model="lineText" name="textarea"  id="" cols="30" rows="10"></textarea>
    <h1>{{ lineText }}</h1>

    <!-- Checkbox data binding,Get whether or not selected content-->
    <input type="checkbox" name="like" v-model="checked" value="123">
    <h1>{{checked}}</h1>
    <!-- Check box multiple values -->
    <input type="checkbox" name="likes" v-model="fruits" value="Persimmon">
    <input type="checkbox" name="likes" v-model="fruits" value="Banana">
    <input type="checkbox" name="likes" v-model="fruits" value="Grape">
    <input type="checkbox" name="likes" v-model="fruits" value="Apple">
    <h1>{{fruits}}</h1>

    <!-- Data binding for radio boxes -->
    <input type="radio" name="sex" value="man" v-model="picked">
    <input type="radio" name="sex" value="woman" v-model="picked">
    <h1>{{picked}}</h1>

    <!-- Data Binding for Radio Option Box -->
    <select name="city"  v-model="city">
      <option value="Guangzhou"></option>
      <option value="Shanghai"></option>
      <option value="Beijing"></option>
      <option value="Chengdu"></option>
    </select>
    <h1>{{city}}</h1>

    <!-- Data Binding for Multiple Selection Option Box -->
    <select name="citys"  v-model="citys" multiple >
      <option value="Guangzhou"></option>
      <option value="Shanghai"></option>
      <option value="Beijing"></option>
      <option value="Chengdu"></option>
    </select>
    <h1>{{citys}}</h1>

    <!-- The form gets the selected content or not -->
    <input type="checkbox" name="like" v-model="checked1" true-value="like" false-value="Dislike">
    <h1>{{checked1}}</h1>

    <!-- Modifier -->
    <!-- .lazy/input Become change Event changes value after focus is out of focus -->
    <input v-model.lazy="searchKey1" type="text" @keydown="searchEvent" />
    <h1>{{searchKey1}}</h1>

    <!-- .number Convert input values to numeric types -->
    <input v-model.lazy.number="searchKey2" type="text" @keydown="searchEvent" />
    <h1>{{searchKey2}}</h1>,

    <input v-model.lazy.trim="searchKey3" type="text" @keydown="searchEvent" />
    <h1>{{searchKey3}}</h1>
  </div>
</template>

<script>
// Declarative
export default {
  name: "App",
  data() {
    return {
      searchKey: "Use Baidu Search",
      lineText: "",
      checked: false,
      fruits:[],
      picked:'',
      city:'',
      citys:[],
      checked1:'',
       searchKey1: "Use Baidu Search",
       searchKey2:'Convert to Number Type',
       searchKey3:'Remove whitespace'
    };
  },
  methods: {
    searchEvent: function () {
      console.log("Search event executed!!!");
    },
  },
};
</script>

assembly

Parent component passes data props to child component

Parent component data newContent is bound to content, and child component receives data from parent component through props
The parent component App.vue code is as follows:

<template>
  <div>
    <!-- Parent Component Data newContent Bind to content  -->
    <News :content = "newsContent"></News>
  </div>
</template>

<script>
// Declarative
import News from './components/News.vue'
export default {
  name: "App",
  data() {
    return {
      newsContent:"23 A year old girl and a man opened a room and were caught in the bag!!!"
    };
  },
  methods: {
    
  },
  components:{
    News
  }
};
</script>

The subcomponent App.vue code is as follows:

<template>
    <div>
        <h1>News content{{content}}</h1>
    </div>
</template>
<script>
export default {
    // Subcomponents receive data from parent components through props
    props:["content"]
}
</script>

Providing data to subcomponents through provide rs and inject s

Parent provides data through provide(), and child injects data through inject()
Parent Component Code: App.vue

<template>
  <div>
    <Student></Student>
  </div>
</template>

<script>
import { reactive,provide} from "vue";
import Student from './components/Student.vue'
export default {
  name: "App",
  data() {
    return {
     
    };
  },
  setup() {
     const student = reactive({
      name: "Little Red",
      age: 18,
      grade: "First day",
    });
    // Provide data
    provide("stu", student);
    
    return { };
  },
  components:{
    Student
  },
};
</script>

Subcomponent code: Student.vue

<template>
  <div>
    <h1>userName:{{ name }}</h1>
    <h1>age: {{ age }}</h1>
    <h1>Grade:{{grade}}</h1>
  </div>
</template>

<script>
import { inject } from "vue";
export default {
  setup() {
    // Inject data provided by parent component
   const student = inject('stu')
   return {...student}
  },
};
</script>

Run the screenshot as follows

Child components pass data to parent components: custom events

The child component triggers custom event 1, the parent component listens for custom event 1, and the value listened for is given to custom event 2
The App.vue code is as follows:

<template>
  <div>
    <!-- Child components pass data to parent components and listen sendParentMsg Run custom events when triggered sendChildMsg -->
    <Login @sendParentMsg ="getChildMsg" ></Login>
    <h1>Values obtained from child elements:{{msg}}</h1>

  </div>
</template>  

<script>
// Declarative
import Login from './components/Login.vue'
export default {
  name: "App",
  data() {
    return {
      msg:''
    };
  },
  methods: {
    getChildMsg:function(value){
      this.msg = value
    }
    
  },
  components:{
    Login
  }
};
</script>

The Login.vue code is as follows:

<template>
    <div>
        <input type="text" v-model="userName">
        <button @click="sendMsg">Submit data to parent component</button>
    </div>
</template>

<script>
export default {
    data(){
        return{
            userName:''
        }
    },
    methods:{
        sendMsg:function(){
            // Trigger custom event sendParentMsg() with $emit (event name, sent event value)
            this.$emit("sendParentMsg",this.userName)
        }
    },
}
</script>

Vue3 life cycle

beforeCreate() and create()

Called when the page is initialized before and after the data is initialized

beforeMount() and mounted()

Render page after initialization is complete before mounting rendering and after mounting rendering

beforeUpdate() and updated()

Called when page data changes

beforeUnmount() and unmounted()

Page data is not rendered when not displayed, vue2 calls beforeDestroy() and destroyed()

Synthetic API: Composition API

  • Composition AP can be used in setup functions

  • Writing order for common and synthetic APIs makes synthetic APIs faster and easier to execute, and helps maintain code

Composition API: single value ref

Import ref
ref() is a variable that becomes responsive

import {ref} from 'vue'
<template>
  <div>
    <h1 @click="changeEvent">Normal way of counting:{{count}}</h1>
     <h1 @click="num+=10">Using synthesis API Count:{{num}}</h1>
  </div>
</template>

<script>
import {ref} from 'vue'

export default {
  name: "App",
  data() {
    return {
      count: 0
    };
  },
  setup(){
    const num = ref(0)
    return{num}
  },
  methods: {
   changeEvent() {
      this.count++
    },
  },

};
</script>

Composition API: Function

<template>
  <div>
     <h1 @click="changeNum">Using synthesis API Defined function count:{{num}}</h1>
  </div>
</template>

<script>
import {ref} from 'vue'

export default {
  name: "App",
  data() {
    return {
    };
  },
  //Synthetic API
  setup(){
  //Instantiate variable num
    const num = ref(0)
    function changeNum(){
        num.value += 10
    }
    //Returns related variables and functions
    return{num,changeNum}
  },
};
</script>

Composition API: Object reactive({})

  • reactive({}) makes an object responsive
  • ... toRefs (object names) are used to deconstruct objects and do not need to be prefixed with object names when invoking object properties
<template>
  <div>
    <!-- Synthesis API Use of objects in -->
    <h1>Full name:{{user.userName}}</h1>
    <!-- Synthesis API Returns a deconstructed object, called without prefixing the object name -->
    <h1>Age:{{age}}</h1>
    <h1 @click="changeType">Type:{{type}}</h1>
  </div>
</template>

<script>
import { reactive,toRefs} from "vue";
export default {
  name: "App",
  data() {
    return {
    };
  },
  setup() {
    // Define Objects
    const user = reactive({
      userName: "millet",
      age: 18,
      type: "Puppies",
    });
    // Change Object Data
    function changeType(){
      user.type = "Super handsome!!!"
    }
    //... toRefs(user) is a deconstruction object
    return { num, changeNum, user, ...toRefs(user),changeType};
  },
};
</script>

Composition API: Listen for data changes

watchEffect

Track changes in data used

Import

import { watchEffect} from "vue";
//Track only type s of values used in anonymous functions
    watchEffect(()=>{
      console.log(user.type)
      console.log("user.type Triggered when the value of")
    })

watch

Trace specified properties
Import

import { watch} from "vue";
  • Listen for a single property
// Single listening
      watch(num,(newNum,oldNum)=>{
      console.log(newNum)
      console.log(oldNum)
      console.log("num Triggered when the value of")
    })
  • Listen for multiple attributes
// Multiple monitoring
     watch([num,user],(newNum,oldNum)=>{
      console.log(newNum)
      console.log(oldNum)
      console.log("Trigger when value changes")
    })

setup Details

Receive parent component data using setup

You need to rely on props to receive data, the parent binds data first, the child receives data through props, and in setup you can calculate responsive content through props

  • The content property contains the content passed in from the parent component

Code for subcomponents:

<template>
    <div>
        <h1>userName:{{userName}}</h1>
        <h1>age: {{age}}</h1>
        <!-- adopt props Generate a sentence -->
        <h1>description: {{description}}</h1>
    </div>
</template>

<script>
import {ref} from 'vue'
export default {
    setup(props,content){
        // Use setup to receive props data and props to calculate the content of the response
        const description = ref(props.userName+"Age is"+props.age)
        console.log(content)
        return{description}

    },
    // Receive data from parent component bindings
    props:['userName','age']
}
</script>

Parent Component Code:

<template>
  <div>
    <User :userName = "userName" :age= "age" class="abc"></User>
  </div>
</template>

<script>
import { reactive,toRefs} from "vue";
import User from './components/User.vue'
export default {
  name: "App",
  data() {
    return {
     
    };
  },
  setup() {
    // Define Objects
    const user = reactive({
      userName: "millet",
      age: 18,
      type: "Puppies"
    })
    
    //... toRefs(user) is a deconstruction object
    return {  user, ...toRefs(user)};
  },
  components:{
    User
  },
};
</script>

life cycle

  • Before onBeforeMount mounts rendering
  • After onMounted mounts the rendering
  • Before onBeforeUpdate update
  • After onBeforeUnmount update
    Import first
import {onBeforeMount,onMounted,onBeforeUpdate,onBeforeUnmount} from 'vue'

Reuse

  setup(){
        // Application of Declaring Periodic Functions
        onBeforeMount(()=>{
            console.log("onBeforeMount")
        })
    },

Vue3 routing: vue-router

Basic use of routing

  • Routing: Single-page applications display different content depending on path changes
  • Install Route under Project Path
E:\vuejs\vue3Router01> npm install vue-router@next

HTML
App.vue code:

<template>
  <div>
    <p>
      <router-link to="/">Go to Home</router-link>
      <router-link to="/about">Go to About</router-link>
    </p>

    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: "App",
};
</script>

JS
index.js

import {createRouter,createWebHashHistory} from 'vue-router'

const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]

const router = createRouter({
  history:createWebHashHistory(),
  routes,
})

export default router

main.js

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

import router from './router'

const app = createApp(App)

// Use Routing
app.use(router)

app.mount('#app')

Dynamic Routing

In single-page applications, different content is displayed according to the id of the path

index.js

import {createRouter,createWebHashHistory} from 'vue-router'
//Import Components
import News from '../components/News.vue'
import NotFound from '../components/NotFound.vue'
//Add Component to Route
const routes = [
  {path:'/news/:id',component: News},
  {path:'/:path(.*)',component: NotFound}
]

const router = createRouter({
  history:createWebHashHistory(),
  routes,
})

export default router

news.vue

<template>
    <div>
        <h1>News Page{{$route.params.id}}</h1>
    </div>
</template>
<script>
export default {
    mounted(){
        console.log(this.$route)
    }
}
</script>

NotFound.vue

<template>
    <div>
        <h1>Page not found</h1>
    </div>
</template>


Routing Regular and Duplicate Parameters

  • \d+: id must be a number
  • +: id has at least one
  • *:id may or may not be repeated multiple
  • ?: IDs are optional, not repeatable, not multiple

index.js

mport News from '../components/News.vue'
import Article from '../components/Article.vue'
import Film from '../components/Film.vue'
import Song from '../components/Song.vue'
import Vidio from '../components/Vidio.vue'
import NotFound from '../components/NotFound.vue'

const routes = [
  {path:'/news/:id',component: News},
  // \d+: id must be a number
  {path:'/article/:id(\\d+)',component: Article},
  // +: id has at least one
  {path:'/film/:id+',component: Film},
  // *:id may or may not be repeated multiple
  {path:'/song/:id*',component: Song},
  // ?: IDs are optional, not repeatable, not multiple
  {path:'/vidio/:id?',component: Vidio},
]

Nested Route

The UI of some applications consists of nested, multilevel components. In this case, the parameters (id s) of a URL are different, the corresponding nested components have different structures, the main structure is the same, and the nested structure is different
The key code for index.js is as follows:

import User from '../components/User.vue'
import Hengban from '../components/Hengban.vue'
import Shuban from '../components/Shuban.vue'

const routes = [
  {path:'/user/',
  component: User,
  children:[
    {path:'hengban',component:Hengban},
    {path:'shuban',component:Shuban}
  ]
},
]

User.vue

<template>
    <div>
        <h1>user page</h1>
        <router-view></router-view>
    </div>
</template>

Hengban.vue

<template>
    <div>
        <h1>This is a horizontal page</h1>
    </div>
</template>

Shuban.vue

<template>
    <div>
        <h1>This is a vertical page</h1>
    </div>
</template>

Vertical run view

Programmatic navigation: jump pages using js

Navigate to another location

In addition to <router-link to="url">which is used to create anchor tags for declarative navigation, we can use the instance method of the router to do this programmatically.

  1. Parameters can be string paths
this.$router.push("/news/:id")
  1. Parameter is an object with path
this.$router.push({path: '/news/:id'})
// Carry Parameter Jump
this.$router.push({path: '/news/123456'})
  1. Named routes with parameters, let routers build paths
this.$router.push({name:'film',params:{id:123}})
  1. Path with query
 this.$router.push({path:'/vidio',query:{search:'Bend to death'}})

Replace current location

 this.$router.replace({path: '/news/123456'})

Replace current location

This method takes a single integer as a parameter and indicates the number of steps forward or backward in the history stack, similar to window.history.go(n).

<button @click="$router.go(1)">Forward</button>
<button @click="$router.go(-1)">Back off</button>

Naming routes and redirections and aliases

Named Route

You can have multiple router-views and name each router-view, and a router-view has no name with default as its name.

App.vue Key Code

<router-view name="ShopTop"></router-view>
<router-view></router-view>
<router-view name="ShopFooter"></router-view>

index.js key code

import ShopMain from '../components/ShopMain.vue'
import ShopTop from '../components/ShopTop.vue'
import ShopFooter from '../components/ShopFooter.vue'

 {
    path: '/shop',
    components: {
      default:ShopMain,
      ShopTop:ShopTop,
      ShopFooter:ShopFooter
    }
  },

ShopMain.vue Key Code

<template>
    <div>
        <h1>ShopMain primary coverage</h1>
    </div>
</template>

ShopTop.vue key code

<template>
    <div>
        <h1>ShopTop Header Component</h1>
    </div>
</template>

ShopFooter.vue Key Code

<template>
    <div>
        <h1>ShopFooter Bottom Component</h1>
    </div>
</template>

Redirect: redirect

  • Redirection is also done in the routes configuration. From/a to redirection/b:
const routes = [{ path: '/home', redirect: '/' }]
  • Redirection can also target named routes:
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]
  • Redirection can also use a function for dynamic redirection
    That is, the input/mall route jumps to the/shop page
const routes = [
	{
    path:'/mall',
    redirect:(shop)=>{
      return {path:'/shop'}
    }
  },
]

Alias: alias

The alias / home for / shop means that the URL still exists / store when the user accesses / store, but it matches / shop as if the user is accessing it. Multiple aliases by array

{
    path: '/shop',
    alias: '/store',
    components: {
      default:ShopMain,
      ShopTop:ShopTop,
      ShopFooter:ShopFooter
    }
  },

Routing mode

Hash mode

A # appears with a hash-mode URL, and this part of the URL is never sent to the server, so it does not require any special handling at the server level

import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    //...
  ],
})

HTML5 mode

With HTML5 mode, URL s will look "normal" and requests will be sent to the server. So you need to configure the appropriate server

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    //...
  ],
})

Navigation Guard

The navigation guard provided by Vue router is primarily used to protect navigation by redirecting or canceling navigation. There are several ways to connect to the routing navigation process: globally, within each route or component.

router.beforeEach

Global Navigation Guard
index.js

router.beforeEach((to, from,next) => {
  // ...
  // explicitly return false to cancel the navigation
  console.log(to)
  console.log(from)
  next()
})

Jump from store page to page page page

router.beforeResolve

Global protection, triggered when route jump is complete

router.beforeResolve(async to => {
  if (to.meta.requiresCamera) {
    try {
      await askForCameraPermission()
    } catch (error) {
      if (error instanceof NotAllowedError) {
        // ... handle the error and then cancel the navigation
        return false
      } else {
        // unexpected error, cancel the navigation and pass the error to the global handler
        throw error
      }
    }
  }
})

beforeEnter

Single route protection, triggered before entering a route

 {
    path: '/shop',
    alias: '/store',
    components: {
      default: ShopMain,
      ShopTop: ShopTop,
      ShopFooter: ShopFooter
    }
  },

Jump from store page to page page page

Internal Component Protection

Written in Components

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave
 // Navigation protection within components
  beforeRouteEnter() {
    console.log("Routing Entry Component");
  },
  beforeRouteUpdate() {
    console.log("Route Update");
  },
  beforeRouteLeave() {
    console.log("Route Leave");
  },

State Management

Responsive object management via reactive

inject subcomponents through reactive responsive objects, then through dependent provide rs and injects
index.js

import { reactive} from 'vue'

// State Management Warehouse
const store = {
    state : reactive({
        message:"Hello"
    }),
    setMessage(value){
        this.state.message = value;
    }
}
export default store

Parent component: App.vue

import store from './store/index.js'
export default {
provide:{
    store
  }
}

Sub-component: HelloWord.vue

inject:['store']

Vuex State Management

home.vue
Call $store

<template>
  <div class="home">
    <h1>Quantity of goods:{{ $store.state.count }}</h1>
    <h2>Commodity price: 100</h2>
    <h1>Total commodity price:{{ $store.getters.totalPrice }}</h1>
    <button @click="changeEvent">Add quantity</button>

    <h1>Paragraph</h1>
    <p v-for="(item,i) in $store.state.dzList" :key="i">{{item.text}}</p>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";

export default {
  name: "Home",
  components: {
    HelloWorld,
  },
  methods: {
    changeEvent: function () {
      // Method of Triggering State
      // Triggering parameterless methods
      // this.$store.commit("setCount");
      // Method with parameters touched
      this.$store.commit("setCountNum", 3);
    },
  },
  mounted:function(){
    this.$store.dispatch('getDz')
  }
};
</script>

index.js
Use store

import { createStore } from 'vuex'

// Manage data used globally
export default createStore({
  // Setting up global data
  state: {
    count:0,
    dzList:[]
  },
  /**
   * Methods with computed attributes
   */
  getters:{
    totalPrice:function(state){
      return state.count*100
    }

  },

 /**
  * Synchronization method
  * Method of modifying state
  */
  mutations: {
    // No parameters
    setCount:function(state){
      state.count++;
    },
    // Has Parameters
    setCountNum:function(state,num){
      state.count+=num;
    },

    setDzList:function(state,arr){
      state.dzList = arr;
    }
  },
  /**
   * Asynchronous methods
   * Request to modify data using Ajax
   */
  actions: {
    getDz:function(context){
      // Open free API
    let api = "https://api.apiopen.top/getJoke?page=1&count=10&type=text";
    // Make a request
    fetch(api)
      .then((res) => res.json())
      .then((result) => {
        console.log(result)
        context.commit('setDzList',result.result)
      });
    }
  },
  modules: {
  }
})

map auxiliary function

  • mapState
  • mapGetters
  • mapMutations
  • mapActions
    map mapping makes data calls easier and allows you to use variable names directly without adding $store.state
    Component Home.vue
import {mapState, mapGetters,mapMutations,mapActions} from 'vuex'

export default {
  name: "Home",
  components: {
    HelloWorld,
  },
  /**
   * Map state to component
   * Call data directly
   */
  computed:{
  //Mapping Data
    ...mapState(['count']),
    ...mapState({
      productCount:(state)=>state.count
    }),
    //Mapping Calculation Properties
    ...mapGetters(['totalPrice'])
  },
  methods: {
    changeEvent: function () {
      this.$store.commit("setCountNum", 3);
    },
    //Mapping methods to change state
    ...mapMutations(['setCountNum']),
    ...mapActions(['getDz'])
  },
  mounted:function(){
    this.$store.dispatch('getDz')
  }
};

vue3 for front-end and back-end interaction

By fetch()

Key Code Snippets

// Get data to display on the page
  setup() {
    // Open free API
    let api = "https://api.apiopen.top/getJoke?page=1&count=10&type=text";
    // Make a request
    fetch(api)
      .then((res) => res.json())
      .then((result) => {
        store.setDzList(result.result);
        console.log(result.result);
      });
  return {
      store
    };

Through axios()

Terminal Installation axios:npm install axios --save

import axios from 'axios'

 // Get data to display on the page
  setup() {
    // Open free API
    let api = "https://api.apiopen.top/getJoke?page=1&count=10&type=text";
    // Make a request
    axios.get(api).then((result)=>{
       console.log(result)
       store.setDzList(result.data.result)
      // store.setDzList(result);
    })
    return {
      store
    };
  },

vite configuration cross-domain request

Cross-domain profile vite.config.js

/**
 * Configuration files for cross-domain servers
 */

module.exports = {
    proxy :{
        '/api':{
            target: 'https://pvp.qq.com/',
            changeOrigin:true, //Is cross-domain allowed
            rewrite:  path => path.replace(/^\/api/,'')
        }
    }
   
}

Mock.js Simulate Getting Data

Links: Click to Jump to Official Website.
You can intercept Ajax requests and return simulated response data

index.js

import Mock from 'mockjs'
Mock.mock(
    "/user/userinfo",
    "get",
    (req,res)=>{
        console.log(req,res)
        return{
            username:"Old Chen",
            type:"Handsome!"
        }
    }
)

Use of vue scaffold cli

Install scaffold cli
npm install -g @vue/cli

View Version
vue --version

Create Project
vue create vueproject01

Select Version

Switch to Project Path
cd vueproject01

Function

npm run serve

Modular management vuex

Import module user,user1 in store

import { createStore } from 'vuex'
import user from './user.js'
import user1 from './user1.js'

// Manage data used globally
export default createStore({
  // Setting up global data
  state: {
   ...
  },
  getters:{
   ...
  },

  mutations: {
  ...
  },
  actions: {
	...
  },
  modules: {
    user,
    user1
  }
})

User module, user.js code as follows:

/**
 * User module
 */

const user = {
    state: () => ({
        username: "Old Chen",
        age: 30
    }),
    mutations: {
        setUsername:function(state){
            state.username = "Xiao Chen"
        },
        setAge:function(state){
            state.age = 40
        }
    },
    actions: {
        asyncSetAge:function(context){
            setTimeout(()=>{
                context.commit('setAge')
            },3000)
        }
    },
    getters: {
        description:function(state,getters,rootState){
            return state.username + 'Age is' + state.age+'Age!'
        }
    }
}

export default user

Namespace

Role: Distinguish each module in case each module's getters and actions must have the same name

const user = {
    //  Namespace
    namespaced: true,
	.....
export default user

Rendering User.vue in Routes
To add a module name

  <!-- Namespace Writing -->
    <h1>User name:{{ $store.state.user1.username }}</h1>
    <h1>Age:{{ $store.state.user1.age }}</h1>
    <h1>Description:{{ $store.getters["user1/description"] }}</h1>
    <button @click="changeAge1">Modify Age</button>

Writing of Auxiliary Functions in Modules

<template>
<!-- Namespace:Writing of Auxiliary Functions -->
    <h1>User name:{{ user1.username }}</h1>
    <h1>Age:{{ user1.age }}</h1>
    <h1>Description:{{ description }}</h1>
    <button @click=" setAge">Asynchronous Modification Age</button>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
  computed: {
    ...mapState(["user1"]),
    ...mapGetters("user1", ["description"]),
    ...mapMutations('user1',['setAge'])
  },
  
  methods: {
    ...mapActions("user1", ["asyncSetAge"]),
  },
};
</script>

Tags: Javascript Front-end Vue Vue.js

Posted on Tue, 09 Nov 2021 11:38:47 -0500 by kirtan007