IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue中组件通信 -> 正文阅读

[JavaScript知识库]Vue中组件通信

前言

??组件之间数据传输。
template中用div包裹html元素是因为,template中只能包裹一个盒子。

1 父传子

通过属性值props接收

??父传子:自定义属性 + props
??props用于接收来自父组件的数据。
??父传子:1)把数据当成子的自定义属性 2)在子对象中接收。
??子组件需要在父组件中注册。

let Son = { 
            template:"#son",
=============================props的写法1=============================
            props:{
                title:String,  // 期待父给我传递的类型是String类型
                abc:String,  // 期待父给我传递的类型是String类型
            }
=============================props的写法2=============================
            props:{
                title:{
                    type:String,   // 期待父给我传递的类型是String类型
                    // required:true  // 父要使用子组件,必须要传title  不传就报错
                    default:"我是一个默认值"  //如果没传title指定默认值
                },
                abc:String, 
            }
=============================props的写法3=============================
            props:["title","abc"]//传啥 要啥 不在乎数据类型
        }
        
            // 把Son组件对象注册到了Father组件中
let Father = { 
            template:"#father",
            components:{
                Son
            }
}
    </script>

2 子传父

通过事件传值 $emit

??子传父:自定义事件 + $emit
??同样需要在父组件中注册。

        <Son @click="g"></Son>写在父组件中 这里的事件名click就只是名字而已
        let Son = { 
            template:"#son",
            // 给son模板中提供方法的
            data(){
                return{
                    msg:"son中的数据"
                }
            },
            methods:{
                k(){
                    // 写代码 触发Son身上的自定义事件
                    this.$emit("click",this.msg)//当前组件实例 前者是事件,后者是数据
                }
            }
        }

3 处理边界情况(组件通信方案)

以下内容子组件据需注册到父组件中。

    <div id="app">
        <h1>{{msg}}</h1>
        <hr>
        <compa></compa>
    </div>

3.1 $root(获得根组件实例)

??在每个 new Vue 实例的子组件(在根实例中注册的)中,其根实例可以通过 $root property 进行访问。

??this.$root 可以得到根组件实例在这里插入图片描述

        let compa = {
            template: `
                <h1>compa组件------<button @click="fn">点我</button></h1>
            `,
            methods: {
                fn() {
                    // 在一个子组件中,可以通过$root,来获取根组件实例
                    console.log(this.$root);
                    console.log(this.$root.msg);
                    this.$root.f1()
                    // 表示修改根组件中的数据
                    this.$root.msg = "hi vue"
                }
            }
        }
        var vm = new Vue({
            el: '#app',
            data: {
                msg: "hello vue"
            },
            methods: {
                f1() {
                    console.log("f1.....");
                }
            },
            components: {
                compa
            },
        })

3.2 $parent(获得父组件实例)

??this.$parent 得到父组件实例在这里插入图片描述

        console.log(this.$parent);
        console.log(this.$parent.a);
        this.$parent.gn()

3.3 $children(获得子组件实例)

??this.$children 得到子组件实例
??得到的是一个数组,原因是子可以有多个。

        console.log(this.$children);
        console.log(this.$children[0]);
        console.log(this.$children[0].a);
        this.$children[0].kn()

3.4 $refs(获得子组件实例)

??this.$refs.xxx获得ref为xxx的子组件实例
??如果把ref写在普通的标签上,和id一样,是为了获取这个DOM元素

        <input type="text" ref="ipt" value="123">

??如果把ref写在一个组件上,是为了获取这个组件实例(赋予ID引用)

        <compa ref="a"></compa>

??这样在任意地方通过this.$refs.xxx获得ref为xxx的子组件的实例

            mounted(){
                // 得到a组件的实例
                console.log(this.$refs.a);
                console.log(this.$refs.a.number);
                this.$refs.a.kn()
                
                console.log(this.$refs.b.value);
            },

3.5 provide & inject依赖注入

??作用:可实现跨组件传值,数据的流只能是向下传递

??provide : 必须在分级组件(不一定是app.vue)进行使用,用来给后代组件注入依赖(属性或方法)。
??inject : 必须在子组件进行使用,用来获取根组件定义的跨组件传递的数据。

??provide在父中提供数据,在子子孙孙组件中都可以使用数据。
??可以实现跨级传输数据

        var app = new Vue({
            el: '#app',
            data: {
                username:"wangcai"
            },
            methods:{
            },
            // 在父中提供数据,在子子孙孙中可以消费数据
            provide(){               //作为方法使用
                return {
                    username:this.username
                }
            },
            // provide:{               //作为对象使用
              
            //         username:this.username
                
            // },
            components:{
                compa
            }
        })

??子或孙组件:

        let compb = {
            inject:["username"],       //接收数组
            // inject:{                //接收对象
            //     username:{
            //         default:'默认值' //指定默认值
            //     }
            // },
            template:`
                <h1>compb组件----------------{{username}}</h1>
            `,
        }

3.6 $attrs

??当一个组件中没有声明任何 prop 时,this.$attrs 可以获取到所有父作用域的属性绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传给其内部组件 —— 在创建高级别的组件时非常有用。

 props:["a","b","c"],
 $attrs  props可以接收数据,
 $attrs可以接收所有的数据
 并没有使用props接收a b c 但是$attrs中已经接收完毕
        <son :a="1" :b="2" :c="3"></son>
        let grandSon = {
            template:`
                <div>--------- grandSon组件----{{data}}-----</div>
            `,
            props:["data"],
        }
        let son = {                                  //$attrs方法
            template:`                                
                <div>--------- Son组件 ---------<grandSon :data="$attrs" /></div>
            `,
            // template:`                             props方法
            //     <div>--------- Son组件 ---------<grandSon :a="a" :b="b" :c="c" /></div>
            // `,
            components:{
                grandSon
            }
        }

3.7 $listeners

??v-on:click="xx" 绑定点击事件
??v-on=$listeners 绑定多个自定义事件

        <!-- @f1="f1" @f2="f2" @f3="f3" 在son组件上绑定三个自定义事件 -->
        <son @f1="f1" @f2="f2" @f3="f3"></son>
        
        let grandSon = {
            template:`
                <div>--------- grandSon组件----<button @click="kn">触发</button>-----</div>
            `,
            // props:["fn"],
            methods:{
                kn(){
                    // this.fn.f1()
                    this.$listeners.f3()//接收 或者触发方法
                }
            }
        }
        let son = {// <grandSon v-on="$listeners" />    v-on="$listeners"在grandSon组件上绑定了三个自定义事件
            template:`
                <div>--------- Son组件 ---------<grandSon v-on="$listeners" /></div>
                //注释<div>--------- Son组件 ---------<grandSon :fn="$listeners" /></div>
            `,
            mounted(){
                // console.log(this.$listeners);
            },
            components:{
                grandSon
            }
        }

3.8 event-bus(时间总线)

        事件总线:
            new一个Vue,可以创建一个根实例,也可以创建一条事件总线。

        在事件总线上有一个机制,叫发布订阅:
            发布:在合适的时机就可以发布    $emit()
            订阅:订阅某个公众号   $on()

        其实事件绑定也是发布订阅:
            <button onclick="alert(6666)">登录</button>

            事件绑定:订阅
            当点击按钮时:发布
        // 创建事件总线  使用一个空的 Vue 实例作为中央事件总线
        let eventBus = new Vue();
        
========根组件中发布meassge
        methods:{
            fn(){
                eventBus.$emit("meassge","hello 事件总线");
            }
        },
========其他组件中订阅meassge
        mounted(){//生命周期中获取
            eventBus.$on("meassge",function(msg){
                console.log("message这个事发生了...",msg);
            })
        },

3.9 sync(修饰props)

??sync对 props 起到了一种修饰的作用,使用 .sync 进行修饰的 props 意味子组件有修改它的意图,这种情况下它只起到一个标注性作用,有它没它都不会影响逻辑。

??:xxx="xxx" @update:xxx="fn" 可以写成:xxx.sync="xxx",减少代码量
??同时也不用在根实例methods中写

<body>
    <div id="app">
        <!-- @update:username="fn"  自定义事件 -->
        <!-- 事件名是:update:username -->
        <!-- <custom-input :username="username" @update:username="fn"></custom-input> -->
        <!-- 修饰符sync  可以对上面的代码进行简写 -->
        <custom-input :username.sync="username" ></custom-input>
        <hr>
        <h1>{{username}}</h1>
    </div>

    <script>
        Vue.component("custom-input",{
            template:`
                <input type="text" :value="username" @change="$emit('update:username',$event.target.value)" />
            `,
            props:["username"]
        })
        var app = new Vue({
            el: '#app',
            data: {
                username:"wangcai"
            },
            methods:{
                // fn(msg){
                //     this.username = msg;
                // }
            }
        })

    </script>
</body>

??文章参考:Vue 组件通信 12 种解决方案

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 11:33:33  更:2021-07-25 11:35:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 14:54:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码