Vue 6 种组件通信方式

发布于 2024-10-23 04:23:11 字数 7958 浏览 6 评论 0

一、父→子

第一种:使用 props

  1. 先给父组件中绑定自定义的属性
  2. 在子组件中使用 props:[ ' '] 接收父组件传递的数据,该数据是只读的
  3. 可以在子组件中任意使用

第二种:父组件通过 provide来提供 数据 或 方法 ,子组件中通过inject 来注入变量。

provideinject 主要在**开发高阶插件/组件库 **时使用。并不推荐用于普通应用程序代码中。

  • provideObject | () => Object
  • injectArray<string> | { [key: string]: string | Symbol | Object }

inject 选项应该是:

  • 一个字符串数组,或
  • 一个对象,对象的 key 是本地的绑定名,value 是:
    • 在可用的注入内容中搜索用的 key (字符串或 Symbol),或
    • 一个对象,该对象的:
      • from property 是在可用的注入内容中搜索用的 key (字符串或 Symbol)
      • default property 是降级情况下使用的 value

提示:provideinject 绑定并 不是可响应的 。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

不论子组件有多深,只要调用了 inject 那么就可以注入 provide 中的数据。而不是局限于只能从当前父组件的 prop 属性来获取数据, 只要在父组件的生命周期内,子组件就可以调用 :

<script>
Vue.component('Child', {
    data() {
      return {
        msg: ''
      }
	},
	template: `
        <div>
            我是孩子{{ msg }}
        </div>
	`,
	inject: ['app'],
	created() {
		this.msg = this.app;
	}
});

Vue.component('Parent', {
    template: `
    <div>
        <p>我是 Parent</p>
        <Child/>
    </div>
    `
});
    
var App = {
    data() {
    	return {}
	},
	provide: {
		app: 'i am App' /*app 属性名*/
	},
	template: `
        <div>
            <h2>我是入口组件 App</h2>
            <Parent/>
        </div>
	`
};
new Vue({
	el: '#app',
	data() {
		return {}
	},
	components: {
		App,
	},
	template: `
		<App/>
	`
})
</script>

注意:依赖注入还是有负面影响的。它将你应用程序中的组件与它们当前的组织方式耦合起来,使重构变得更加困难。同时所提供的属性是非响应式的。这是出于设计的考虑,因为使用它们来创建一个中心化规模化的数据跟 使用 $root 做这件事都是不够好的。

如果你想要共享的这个属性是你的应用特有的,而不是通用化的,或者如果你想在祖先组件中更新所提供的数据,那么这意味着你可能需要换用一个像 Vuex 这样真正的状态管理方案了

二、子→父

​ 使用 $emit

  1. 在父组件绑定自定义的事件
    1. 在子组件中触发原生的事件,在函数中使用 this.$emit 触发父组件中自定义的事件
<script>
Vue.component("Parent", {
  data() {
    return {
      msg: "我是父组件中的数据",
    };
  },
  template: `
	                <div>
	                <Vbtn type="primary">denglu</Vbtn>
	                    <p>父组件</p>
	                    <Child :childData="msg" @childHandler='childHandler'/><!--//1.绑定自定义的属性、事件-->
	                </div>
	            `,
  methods: {
    childHandler(val) {
      console.log(val);
    },
  },
});

Vue.component("Child", {
  props: ["childData"], //2.在子组件中使用 props 接收父组件传递的数据
  template: `
	                <div>
	                    <p>孩子组件接收{{childData}}</p>
	                    <input type="text" v-model="childData" @input='changeValue(childData)' /> <!--//任意使用-->
	                </div>
	            `,
  methods: {
    changeValue(val) {
      //自定义的事件一定通过 this.$emit() 去触发
      //$emit(自定义的事件名,消息 )
      this.$emit("childHandler", val); //2.在子组件中触发原生的事件,在函数中使用 this.$emit 触发父组件中自定义的事件
    },
  },
  
});
</script>

三、父↔子

第一种:使用 $attrs$listeners、$emit

<script>
Vue.component("C", {
  template: `
	            <div>
	              <div @click='cClickHandler'>{{ $attrs.messagec }}</div>
	            </div>
	          `,
  methods: {
    cClickHandler() {
      this.$emit("getCData", "我是 c 的数据");
    },
  },
});

Vue.component("B", {
  template: `
	        <div>
	            <C v-bind="$attrs" v-on="$listeners"></C>
	        </div>
	      `,
});

Vue.component("A", {
  data() {
    return {};
  },
  props: ["message"],
  template: `
	            <div>
	                <B v-bind="$attrs" v-on="$listeners"></B>
	                <!-- <input type="text" v-model="$attrs.messagec"/> -->
	            </div>
	      `,
});

new Vue({
  data() {
    return {
      msg: "我是父组件的内容",
      messagec: "hello c",
    };
  },
  template: `
	            <div>
	                <p>这是一个父组件</p>
	                <A :messagec="messagec" v-on:getCData="getCData"></A>
	             </div>
	  `,
  methods: {
    //执行 c 组件的触发的函数
    getCData(val) {
      console.log(val);
    },
  },
});
</script>

第二种:使用 this. $parent 、this. $children [0] 完成父子组件的通信

<script>
Vue.component("Child", {
  props: {
    value: String, //v-model 会自动传递一个字段为 value 的 prop 属性
  },
  data() {
    return {
      mymessage: this.value,
    };
  },
  template: `
                <div>
                    <input type="text" v-model="mymessage" v-on:change="changeValue">
                </div>
            `,
  methods: {
    changeValue() {
      //通过如此调用可改变父组件的值
      console.log(this.$parent);
       // 设置子组件的数据
      this.$parent.message = this.mymessage;
    },
  },
});

Vue.component("Parent", {
  data() {
    return {
      message: "I am your Parent",
    };
  },
  template: `
                <div>
                    <p>我是 Parent 组件{{ message }}</p>
                    <button @click="changeChildValue">changeChildValue</button>
                    <Child></Child>
               </div>
            `,
  methods: {
    changeChildValue() {
        // 设置子组件的数据
      this.$children[0].mymessage = "hello";
    },
  },
});
</script>

四、兄弟组件通信

使用 bus 中央事件总线的方式

新建一个 Vue 事件 bus 对象,然后通过 bus. 触发事件,.emit 触发事件,bus.on 监听触发的事件

<script>
    var bus = new Vue();
    bus.$emit('globalEvent', val);
    bus.$on('globalEvent', (val) => {
        this.brother2Msg = val;
    })
</script>
<script>
    var bus = new Vue();
    Vue.component("brother2", {
        data() {
            return {
                msg: "hello i am brother2",
            };
        },
        template: `
<div>
<p>我是 brother2</p>
<input type="text" v-model="msg" @input="passData(msg)"/>
    </div>
`,
        methods: {
            passData(val) {
                //触发全局事件 globalEvent
                bus.$emit("globalEvent", val);
            },
        },
    });

    Vue.component("brother1", {
        data() {
            return {
                msg: "hello i am brother1",
                brother2Msg: "",
            };
        },
        template: `
<div>
<p>我是 brother1</p>
<p>brother2 传递过来的数据:{{ brother2Msg }}</p>
    </div>
`,
        mounted() {
            //绑定全局事件 globalEvent
            bus.$on("globalEvent", (val) => {
                this.brother2Msg = val;
            });
        },
    });

    var App = {
        data() {
            return {
                msg: "我是父组件的内容",
                messgaec: "hello c",
            };
        },
        template: `
<div>
<brother1></brother1>
<brother2></brother2>
    </div>
`,
    };
    new Vue({
        el: "#app",
        components: {
            App,
        },
        template: `
<App/>
`,
    });
</script>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

上一篇:

下一篇:

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

0 文章
0 评论
21 人气
更多

推荐作者

謌踐踏愛綪

文章 0 评论 0

开始看清了

文章 0 评论 0

高速公鹿

文章 0 评论 0

alipaysp_PLnULTzf66

文章 0 评论 0

热情消退

文章 0 评论 0

白色月光

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文