Vue learning --- based on components in vue2, component communication, ref

Vue learning - based on components in vue2

This article is based on vue2.x the development environment

1. Components

1.1 Register components

A .vue file created under the components folder under the src folder under the project folder is a component. This is used in the script of the component, and this this represents the instance of the current component

partial registration

First import the component through the import component name from 'component path'; register the component with components in export default

Sample code:

Write in the App.vue file

<template>
  <!-- 一个.vue文件就是一个组件, 一个项目中只有一个根组件 App.vue -->
  <!-- 一个.vue文件内部一般是由三部分组成: template , script , style -->
  <!-- template 内部写标签 , 只能有一个根元素 -->
  <!-- script 内部写js逻辑 , 内部需要 export default {}, 所有的js代码都需要写在这里 -->
  <!-- style 内部写css样式 , 可以通过lang='xx'指定style内部的css语法 , 可以通过设置 scoped 属性 让多个.vue文件之间的样式互不影响 -->
  <div id="app">
    <!-- 搜索框 -->
    <Search></Search>

    <!-- 轮播图 -->
    <Swiper></Swiper>

    <!-- 列表 -->
    <List></List>

    <!-- Tabbar -->
    <Tabbar></Tabbar>

  </div>
</template>

<script>
//导入组件
import Search from './components/Search.vue'
import Swiper from './components/Swiper.vue'
import List from './components/List.vue'
import Tabbar from './components/Tabbar.vue'

export default {
  components:{ //负责注册组件( 局部组件 , 只能在当前注册的文件中使用 )
    // Search,
    Swiper,
    List,
    Tabbar
  }
}
</script>

<style lang="scss">
// 这里不加scoped , 因为 这里一般写全局样式
*{
  margin: 0;
  padding: 0;
}
</style>

global registration

Still import the component first, then register the component through vue.component('component name', import component name)

Sample code:

in the main.js file

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 导入Search组件
import Search from './components/Search.vue'
// 注册组件(全局组件,可以在所有的.vue文件中使用)
Vue.component('Search', Search);

//实例化Vue对象
new Vue({
    
    
  render: h => h(App),
}).$mount('#app')

Component usage

Using components (can be global components or local components)

Used in the App.vue file: <component name/> or <component name> <component name/>

1.2 Import and export of modules (a module is a js file)

Create a file utils under the src folder under the project folder to place the created js file

The first type: default export

Export: export default variable name to be exported

Import: import exported variable name from 'path'

Sample code:

The newly created js file is exported:

//定义函数
function add(a,b){
    
    
    return a+b;
}

//默认抛出(导出)
export default add;

main.js file import:

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false
// 默认导入 可以给默认导入的数据改名
// 默认导出和默认导入 配合使用
import abc from './utils/a'
console.log( abc(10,20) );

//实例化Vue对象
new Vue({
    
    
  render: h => h(App),
}).$mount('#app')

The second type: named export

Export: export { variable name 1, variable name 2,...}

Import: import { variable name 1, variable name 2, ... } from 'path'

Sample code:

js file export:

function sub(a,b){
    
    
    return a-b;
}
function mul(a,b){
    
    
    return a*b;
}

//命名导出
export {
    
    
    sub,
    mul
};

main.js file import

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 命名导入
// 命名导入导出是对应的配合使用的,命名变量名字要相同

// {sub,mul}解构赋值,解析出你想要导入的文件
// 命名导入,必须以{}的形式导入解构时不能改名字要和导出中的名字一样
import {
    
    sub,mul} from './utils/b';

console.log(sub(10,20),mul(10,20));

console.log(abc(10,20));

//实例化Vue对象
new Vue({
    
    
  render: h => h(App),
}).$mount('#app')

1.3 Component lifecycle hooks

Lifecycle hooks are defined methods that execute at a certain stage in the lifecycle of a Vue component instance. An instance object follows different life stages from initialization until it is destroyed. This is a well-known diagram representing the order in which hook functions are executed.

insert image description here
insert image description here

  • beforeCreate: After the instance is initialized and before the creation is completed , the data observer (data observer) and event/watcher event configuration are called before
  • created: Called immediately after the instance is created . In this step, the instance has completed the following configurations: data observer, operation of attributes and methods, event/watch event callback. However, the mount phase has not yet started and the $el property is not currently visible.
  • beforeMount: Called before the mount starts: the relevant render function is called for the first time.
  • mounted: This hook is called after el is replaced by the newly created one vm.$eland mounted to the instance. If the root instance mounts an in-document element, it vm.$elis also in-document when mounted is called.
  • beforeUpdate: Called when the data is updated, before the virtual DOM is patched. This is suitable for accessing the existing DOM before updating, such as manually removing the added event listener.
  • updated: This hook will be called after the virtual DOM is re-rendered and patched due to data changes.
  • beforeDestroy: Called before the instance is destroyed. At this step, the instance is still fully available.
  • destroyed: Which one is called after the Vue instance is destroyed. After calling, everything indicated by the vue instance will be unbound, all event listeners will be removed, and all child instances will be destroyed.

Notice:

  1. The above functions are all periodic functions of the component, and they will be called automatically at a specific moment during the life of the component.
  2. The method in the instantiation period will only be executed for this part
  3. The method in the mount period will only be executed once; for which components must be executed before the mount is completed and can only be executed once, the code can be written in the mounted function, where ajax requests can be sent, timers can be created, and event monitoring can be done.
  4. The two methods in the update period will be executed repeatedly as the component is updated
  5. The destruction period will only be executed once; if operations such as sending ajax requests, creating timers, and event monitoring (scroll bar leave, keyboard events, binding click events) and other operations are performed in the mounted life cycle function, these operations will occupy computer memory, and in the component If the memory is not released in time before destruction, it will cause a memory leak.
  6. $destroy(): The method of destroying the component. The destruction of the component does not necessarily mean that the component disappears, but that the component cannot be used.

Sample code:

App.vue file

<template>
  <!-- 一个.vue文件就是一个组件, 一个项目中只有一个根组件 App.vue -->
  <!-- 一个.vue文件内部一般是由三部分组成: template , script , style -->
  <!-- template 内部写标签 , 只能有一个根元素 -->
  <!-- script 内部写js逻辑 , 内部需要 export default {}, 所有的js代码都需要写在这里 -->
  <!-- style 内部写css样式 , 可以通过lang='xx'指定style内部的css语法 , 可以通过设置 scoped 属性 让多个.vue文件之间的样式互不影响 -->
  <div id="app">
    <h1>count:{
   
   {count}}</h1>
    <button @click="$destroy()">销毁当前组件</button>
  </div>
</template>

<script>
export default {
  data(){
    return {
      count:0,
      timerid:null
    }
  },
  computed:{

  },
  // 以下这些函数都是 组件的生命周期函数,它们在组件生命过程中会在特定时刻自动调用。

  // 实例化期,这里的方法只会执行一次
  beforeCreate(){
    console.log('组件-创建(实例化)前');
  },
  created(){
    console.log('组件-创建(实例化)完成');
  },
  // 挂载期,这里的方法只会执行一次
  beforeMount(){
    console.log('组件-挂载前');
  },
  mounted(){
    // 对于哪些在组件挂载完成前 必须执行而且只能执行一次的代码可以写在这里
    console.log('组件-挂载完成');
    // 在这里可以发送ajax请求,创建定时器,事件监听
    this.timerid = setInterval(()=>{
      this.count++;
    },1000)
  },

  // 更新期,这里的两个方法会随着组件更新  反复执行
  beforeUpdate(){
    console.log('组件-更新前');
  },
  updated(){
    console.log('组件-更新完成');
  },

  // 销毁期,只会执行一次
  beforeDestroy(){

    console.log('组件-销毁前');
    // 如果在 mounted 生命周期函数中做了  发送ajax请求,创建定时器,事件监听 等操作,这些操作会占用计算机内存,在组件销毁前如果没有及时释放这些内存,就会导致内存泄漏。
    clearInterval(this.timerid);
  },
  destroyed(){
    console.log('组件-销毁完成');
  }
}
</script>

<style lang="scss" scoped>

</style>

2. Component communication

The so-called component communication, that is, the data transfer between components and components, includes two aspects:

Ø Data transfer between parent and child components with nested relationship;

Ø Data transfer between sibling components;

Specifically can be divided into:

  • Pass value from parent component to child component
  • Pass value from child component to parent component
  • Cross-level component pass value
  • Passing values ​​between sibling components

2.1 Parent components pass values ​​to child components

When the data exists in the parent component, the data in the parent component needs to be passed to the child component

The parent component passes the value through the custom attribute on the child component, and the child component receives the value through props inside

parent component:

<div id="app">
    <div class="tabs">
      <!-- App.vue与渲染的组件之间是父子关系 -->
      <!-- 所有数据都存在于父组件中,需要将父组件中的数据传到子组件中进行渲染 -->

      <!-- 父组件向子组件传值:父组件在子组件身上通过自定义属性传值,子组件内部通过props接收值 -->
      <!-- 子组件向父组件传值:父组件提前在子组件身上绑定自定义事件,子组件内部通过$emit触发 -->

      <!-- 渲染左侧分类 -->
      <TabLeft :tabs="tabs" ></TabLeft>

      <!-- 渲染右侧分类 -->
      <TabRight ></TabRight>
    </div>
  </div>


export default {
    
    
    data() {
    
    
        return {
    
    
            // 用来保存当前点击的分类下标
            currentIndex: 0,
            tabs: [
                {
    
    
                    tabName: "三文鱼",
                    list: [
                        {
    
     pic: pic1, name: "三文鱼", price: 45 },
                        {
    
     pic: pic1, name: "高级三文鱼", price: 55 },
                        {
    
     pic: pic1, name: "vip三文鱼", price: 65 },
                    ]
                },
                {
    
    
                    tabName: "刺身",
                    list: [
                        {
    
     pic: pic2, name: "刺身", price: 45 },
                        {
    
     pic: pic2, name: "高级刺身", price: 55 },
                        {
    
     pic: pic2, name: "vip刺身", price: 65 },
                    ]
                },
                {
    
    
                    tabName: "大虾",
                    list: [
                        {
    
     pic: pic3, name: "大虾", price: 45 },
                        {
    
     pic: pic3, name: "高级大虾", price: 55 },
                        {
    
     pic: pic3, name: "vip大虾", price: 65 },
                    ]
                },
            ]
        };
    },
    components: {
    
     
      TabRight,
      TabLeft,
     }

Subassembly:

export default {
    // 通过props接收从父组件传来的值,该值是只读的(不能修改)
    // props:['tabs','currentIndex']//数组形式
    props:{//对象形式,可以对传来的数据进行类型验证
        tabs:{type:Array, default:[]},
    }
}

2.2 Subcomponents pass values ​​to parent components

The parent component binds custom events on the child component in advance, and the child component is triggered internally through $emit

on subscribes, emit publishes, on and emit are on the prototype of Vue, and each instance can be called.

parent component:

<div id="app">
    <div class="tabs">
      <!-- App.vue与渲染的组件之间是父子关系 -->
      <!-- 所有数据都存在于父组件中,需要将父组件中的数据传到子组件中进行渲染 -->

      <!-- 父组件向子组件传值:父组件在子组件身上通过自定义属性传值,子组件内部通过props接收值 -->
      <!-- 子组件向父组件传值:父组件提前在子组件身上绑定自定义事件,子组件内部通过$emit触发 -->

      <!-- 渲染左侧分类 -->
      <!-- <TabLeft :tabs="tabs" :currentIndex="currentIndex" @deliverIndex="changelist" ></TabLeft> -->
      <TabLeft :tabs="tabs" :currentIndex="currentIndex" @deliverIndex="changelist" ></TabLeft>

      <!-- 渲染右侧分类 -->
      <TabRight :tabs="tabs" :currentIndex="currentIndex"></TabRight>
    </div>
  </div>
  
 export default {
    data() {
        return {
            // 用来保存当前点击的分类下标
            currentIndex: 0,
            tabs: [
                {
                    tabName: "三文鱼",
                    list: [
                        { pic: pic1, name: "三文鱼", price: 45 },
                        { pic: pic1, name: "高级三文鱼", price: 55 },
                        { pic: pic1, name: "vip三文鱼", price: 65 },
                    ]
                },
                {
                    tabName: "刺身",
                    list: [
                        { pic: pic2, name: "刺身", price: 45 },
                        { pic: pic2, name: "高级刺身", price: 55 },
                        { pic: pic2, name: "vip刺身", price: 65 },
                    ]
                },
                {
                    tabName: "大虾",
                    list: [
                        { pic: pic3, name: "大虾", price: 45 },
                        { pic: pic3, name: "高级大虾", price: 55 },
                        { pic: pic3, name: "vip大虾", price: 65 },
                    ]
                },
            ]
        };
    },
    components: { 
      TabRight,
      TabLeft,
     },
     methods:{
    changelist(index){
      this.currentIndex = index;
    }
  }
  
  

Subassembly:

 <div class="tab" :class="{active:currentIndex ==index}" @click="$emit('deliverIndex',index)" v-for="(item,index) in tabs" :key="index">{
    
    {
    
    item.tabName}}</div>
<div class="tabright">
    <!-- 渲染多个商品(列表) -->
    <div class="good" v-for="(item,index) in tabs[currentIndex].list" :key="index">
        <div class="imgbox">
            <img :src="item.pic" alt="">
        </div>
        <div class="text">
        <div class="name">{
    
    {
    
    item.name}}</div>
        <div class="price">{
    
    {
    
    item.price}}</div>
    </div>
    </div>
  </div>

**Note: **The event name passed in in emit must be all lowercase

2.3 Communication between sibling components

Need to use a public eventbus (communication pipeline) where one component binds the event in advance, and the other sibling component triggers the event and passes the value

Create an empty instance, for example: vm = new Vue({}); as a communication bridge;

Use vm.$on() to listen to custom events in components that need to receive data (usually processed in the mounted function), and process the passed parameters in the callback function (note the this processing in the callback function);

Use vm.$emit() to trigger custom events in components that need to pass values, and pass data;

Instantiate Vue empty instance:

var vm = new Vue({});

step:

1. First create a utils folder in src, create a tools.js file in this folder, instantiate an empty Vue instance in this file, and export

import Vue from 'vue'

// 实例化Vue 并导出
export default new Vue()

2. Use vm.$on() to listen to custom events in components that need to receive data (usually processed in the mounted function)

<div class="list">
        <!-- 渲染多个商品(列表) -->
        <div class="good" v-for="(item,index) in tabs[currentIndex].list" :key="index">
            <div class="imgbox">
            <img :src="item.pic" alt="">
            </div>
            <div class="text">
            <div class="name">{
   
   {item.name}}</div>
            <div class="price">¥{
   
   {item.price}}</div>
            </div>
        </div>
    </div>
    
    import eventbus from '../utils/tools'

export default {
    // 通过props接收从父组件传来的值,该值是只读的(不能修改)
    data(){
        return {
            currentIndex:0
        }
    },
    props:['tabs'],
    mounted(){
        // 绑定事件
        eventbus.$on('deliverIndex',(index=>{
            this.currentIndex = index; //保存接收到的值
        }))
    }
}

3. Use vm.$emit() to trigger custom events in components that need to pass values, and pass data;

It is not necessary to pass a value to trigger an event. It is possible to just trigger this event

Brother component a:

<div class="tabbox">
        <!-- 渲染多个分类按钮 -->
        <div class="tab" :class="{active: currentIndex==index }" @click="handleClick(index)" v-for="(item,index) in tabs" :key="index">{
   
   {item.tabName}}</div>
    </div>
    
    // 导入空实例
import eventbus from '../utils/tools'

export default {
    // 通过props接收从父组件传来的值,该值是只读的(不能修改)
    // props:['tabs','currentIndex'] //数组形式
    data(){
        return {
            currentIndex:0
        }
    },
    props:{//对象形式,可以对传来的数据进行类型验证
        tabs:{type:Array,default:[]}
    },
    methods:{
        handleClick(index){
            eventbus.$emit('deliverIndex',index);//触发事件并传值
            this.currentIndex = index;
        }
    }
}

2.4 Passing values ​​across components

Outer components pass values ​​through provide, and inner components receive values ​​through inject.

Example:

Pass the value in the outer component to the Child1 component, then pass the value to the Child2 component through the Child1 component, and then pass the value to the Child3 component through the Child2 component

Sample code:

App.vue file

<template>
  <!-- 一个.vue文件就是一个组件, 一个项目中只有一个根组件 App.vue -->
  <!-- 一个.vue文件内部一般是由三部分组成: template , script , style -->
  <!-- template 内部写标签 , 只能有一个根元素 -->
  <!-- script 内部写js逻辑 , 内部需要 export default {}, 所有的js代码都需要写在这里 -->
  <!-- style 内部写css样式 , 可以通过lang='xx'指定style内部的css语法 , 可以通过设置 scoped 属性 让多个.vue文件之间的样式互不影响 -->
  <div id="app">
    <Child1></Child1>
  </div>
</template>

<script>
import Child1 from './components/Child1.vue';

export default {
  components:{
    Child1
  },
  // 跨组件传值:外层组件通过provide传值,内层组件通过inject接收值
  provide(){//负责传值给内层组件
    return {
      money:8888,
      list:[1,2,3]
    }

  }
}
</script>

<style lang="scss" scoped>

</style>

Child1.vue file

<template>
  <div class="child1">
    <h1>我是子组件1 - {
   
   {money}}</h1>
    <Child2/>
  </div>
</template>

<script>
import Child2 from './Child2.vue'
export default {
    components:{
        Child2
    },
    inject:['money']
}
</script>

<style>

</style>

Child2.vue file

<template>
    <div class="child2">
      <h1>我是子组件2 - {
   
   {money}}</h1>
      <Child3 />
    </div>
  </template>
  
  <script>
  import Child3 from './Child3.vue'
  
  export default {
      components:{
          Child3
      },
      inject:['money']
  }
  </script>
  
  <style>
  
  </style>

Child3.vue documents

<template>
    <div class="child3">
      <h1>我是子组件3 - {
   
   {money}} - {
   
   {list}} </h1>
    </div>
  </template>
  
  <script>
  export default {
      //inject 接收从外层组件传来的值
      inject:['money','list']
  }
  </script>
  
  <style>
  
  </style>

3.ref

Get the dom node:

Set the ID (alias) for the tag through the ref attribute, and get the dom node corresponding to the ID through this.$refs.xx in the js code

ref is applied to the component

Get the component instance corresponding to the identifier through this.$refs.xx in the js code

Sample code:

<template>
  <div id="app">
    <!-- 通过ref属性给标签设置标识( 别名 ) -->
    <!-- 在js代码中 通过 this.$refs.xx 获取标识对应的dom节点 -->
    <input type="text" ref="phone">
    <h1 ref="title">学习ref</h1>

    <!-- ref应用在组件身上 -->
    <!-- 在js代码中 通过 this.$refs.xx 获取标识对应的组件实例 -->
    <Child ref="ch" />
    
  </div>
</template>

<script>
import Child from './components/Child.vue'

export default {
  components:{
    Child
  },
  mounted(){
    console.log( this.$refs.phone );
    console.log( this.$refs.title );
    console.log( this.$refs.ch );

    //调用子组件的add,sub方法
    this.$refs.ch.add();
    this.$refs.ch.sub();
  }
}
</script>

<style lang="scss" scoped>

</style>

Examples of refs

shopping cart component

<template>
 <div class="shopcart" v-show="visible" @click="changeVisible">
        <!-- @click.事件修饰符 -->
        <!-- @click.stop 阻止事件冒泡 -->
        <!-- @click.ctrl 只有同时按下ctrl键并点击才会触发 -->
        <!-- @click.right 只有按下鼠标右键才会触发 -->
        <!-- @click.native 给子组件绑定原生事件,只有添加active修饰符才会触发 -->
        <div class="content" @click.stop="handleClick">
            <div class="title">
                <span>已选商品</span>
                <span @click="clean">清空</span>
            </div>
            
            <div v-if="list.length != 0" class="list">
                <div v-for="(item,index) in list" :key="index" class="good">
                    <div class="imgbox">
                        <img :src="item.pic" alt="">
                    </div>
                    <div class="text">
                        <div class="name">{
   
   {item.name}}</div>
                        <div class="price">
                            <div>¥{
   
   {item.price}}</div>
                            <div>
                                <span @click="sub(item)">-</span>
                                <span>{
   
   {item.count}}</span>
                                <span @click="add(item)">+</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div v-else class="empty" >购物车空空如也,去逛逛!</div>
        </div>
    </div>  
</template>

<script>
var pic = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202102%2F26%2F20210226073347_50f94.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668131440&t=6df291a148cdb21289e91211d4daea32';

export default {
    data(){
        return {
            visible:false,
            list:[
                { name:'秋刀鱼',price:88,pic,count:1 },
                { name:'大黄鱼',price:777,pic,count:2 },
                { name:'皮皮虾',price:9,pic,count:3 },
            ]
        }
    },
    methods:{
        /* show(){
            this.visible = true;//让购物车显示
        },
        hide(){
            this.visible = false;//让购物车隐藏
        }, */
        changeVisible(){
            this.visible = !this.visible;//让购物车显示/隐藏
        },
        clean(){

        },
        handleClick(){
            console.log('触发了!');
        }
    }
}
</script>

<style lang='scss' scoped>

.shopcart{
    height: 100%;
    width: 100%;
    position: fixed;
    background-color: rgba(0, 0, 0, 0.3);
}
.content{
    position: absolute;
    bottom: 0;
    background-color: white;
    width: 100%;
    padding: 10px;
    box-sizing: border-box;
}
.content .title{
    display: flex;
    justify-content: space-between;
    font-weight: bold;
}
.content .list .good{
    display: flex;
    margin: 10px 0;
}
.content .list .good .imgbox{
    width: 80px;
    margin-right: 10px;
}
.content .list .good .imgbox img{
    width: 100%;
}
.content .list .good .text{
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}
.content .list .good .text .name{
    font-weight: bold;
}
.content .list .good .text .price{
    display: flex;
    justify-content: space-between;
}
.content .list .good .text .price span{
    display: inline-block;
    width: 14px;
    height: 14px;
    text-align: center;
    line-height: 14px;
    background-color: lightskyblue;
    color: white;
    border-radius: 50%;
}
.content .list .good .text .price span:nth-child(2){
    color: black;
    background-color: white;
}
.empty{
    text-align: center;
    padding: 50px;
}
</style>

parent component

<template>
  <!-- 一个.vue文件就是一个组件, 一个项目中只有一个根组件 App.vue -->
  <!-- 一个.vue文件内部一般是由三部分组成: template , script , style -->
  <!-- template 内部写标签 , 只能有一个根元素 -->
  <!-- script 内部写js逻辑 , 内部需要 export default {}, 所有的js代码都需要写在这里 -->
  <!-- style 内部写css样式 , 可以通过lang='xx'指定style内部的css语法 , 可以通过设置 scoped 属性 让多个.vue文件之间的样式互不影响 -->
  <div id="app">
    <Shopcart ref="shopcart"></Shopcart>
    <div class="summary">
      <!-- 通过ref设置的标识 获取子组件实例,进而调用子组件的方法 -->
      <span @click="$refs.shopcart.changeVisible()">购物车</span>
      <span>去结算</span>
    </div>
    <Child @click.native="handleChildClick"/>
  </div>
</template>

<script>
import Shopcart from './components/Shopcart.vue'
import Child from './components/Child.vue'

export default {
    components: { Shopcart,Child },
    methods:{
      handleChildClick(){
        console.log('点击了Child组件');
      }
    }
}
</script>

<style lang="scss">
*{
  margin: 0;
  padding: 0;;
}
.summary{
  position: fixed;
  bottom: 0;
  width: 100%;
  background-color: #555;
  color: white;
  display: flex;
  justify-content: space-between;
  padding: 10px 10px;
  box-sizing: border-box;
}
</style>


@click.event modifier

@click.left: Triggered only when the left mouse button is clicked

@click.right: triggers only when the right button is clicked

@click.middle: The mouse wheel must be clicked to trigger the click event

@click.prevent: Prevent the default behavior, for example: jumping of a tag

@click.ctrl: The click event must be pressed to trigger the Ctrl key

@click.shift: Triggered when the shift key is pressed

@click.native: Native click event when binding the click event to the child component

Custom event: When a child component is used in the parent component, the event directly bound to the child component is a custom event, which must be triggered by the child component vm.$emit() to execute native events: directly in the child component The event bound on the template can be triggered directly after the subcomponent is introduced

Guess you like

Origin blog.csdn.net/m0_53181852/article/details/127598133