隔壁小孩都馋哭的vue组件传值讲解

写在前面:

我是一个坚持学习的技术小白,在博客里分享自己的学习总结记录,如果你也在努力变成更好的自己,可以关注我,一起加油!
如果任何问题或交友,欢迎各位与我联系:[email protected]

正文


vue组件化

组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 js 特性进行了扩展的原生 HTML 元素。

父子组件传值


在 Vue 中,父子组件的关系可以总结为:prop 向下传递, 事件($emit) 向上传递。父组件通过 prop 给子组件下发数据,子组件通过 事件 给父组件发送消息。


注意:
父组件可以向子组件传递数据,传递过来的数据可以随意修改,但子组件不能随意修改父组件传递过来的数据,比如说:父组件向好几个子组件传递相同的数据,其中一个子组件修改值,因为接受到的是引用类型的数据,所以一个组件修改值,可能导致其他子组件引用修改的数据。这也是 Vue 官网提到的 单向数据流的概念。Vue 官网描述

父组件向子组件传值

父组件中需要进行的操作:

  • import 子组件
  • 注册 import 的子组件
  • 使用子组件的地方,v-bind (绑定)要传递的属性值
//parent.vue

<template>
  <div id="app">
    <h3>我是父组件</h3>
    <!-- 子组件, 绑定父组件要传递给子组件的值 -->
    <childCom :child="msg"></childCom>
  </div>
</template>

<script>
import childCom from "./child"; 	//引入子组件
export default {
  components: {		//注册子组件
    childCom
  },
  data() {
    return {
      msg: "哈哈哈"
    };
  }
};
</script>

子组件中接收父组件的值:

  • 使用 props 接收传递的值,props 是一个数组,比如:props:[“child”] , 数组里面的元素都是父组件传递过来的属性名,接收后可以当 data 中定义的属性一样使用,比如:{{child}}
  • props 还可以使用对象方式接收,并设置类型,比如:props:{“child” : {type : String}},其中 type 是该属性值的类型,强调传递的值是 String 类型,它会进行验证,如果不是 String 类型,会报错。还可以设置 属性值的默认值,写法:props : {“child” : {type : String, default = “嘿嘿”}}
// child.vue

<template>
  <div>
    <h3>我是子组件</h3>
    <div>{{child}}</div>
  </div>
</template>

<script>
export default {
  //接收从父组件传递的值
  props: ["child"]
};
</script>

结果展示:

在这里插入图片描述

子组件向父组件传值

父组件中需要进行的操作:

  • 在父组件中 import 子组件,注册子组件,使用子组件并v-bind 属性值
  • 使用子组件时 v-on 绑定方法名
  • 父组件中定义绑定的方法,此方法名要与 v-on 绑定的方法名一致
// parent.vue

<template>
  <div id="app">
    <h3>我是父组件</h3>
    <!-- 使用子组件,绑定属性值与方法 -->
    <childCom :child="msg" @passMethods="passMethod"></childCom>
  </div>
</template>

 <script>
import childCom from "./child"; //引入子组件
export default {
  //注册子组件
  components: {
    childCom
  },
  data() {
    return {
      msg: "哈哈哈"
    };
  },
  methods: {
    //子组件中绑定的方法
    passMethod(data) {
      this.msg = data;
    }
  }
};
</script>

子组件向父组件传递值:

  • 用 emit 向父组件传递值,比如:this.$emit(“passMethods”, “修改父组件的msg”); 第一个参数是父组件中绑定的事件(@passMethods),这两个名字一定要相同,第二个参数是传递的值
  • 子组件标签中绑定 emit 的方法
// child.vue

<template>
  <div>
    <h3>我是子组件</h3>
    <!-- 插值表达式,显示传递的值 -->
    <div>{{child}}</div>
    <br />
    <!-- 按钮,点击事件绑定方法 -->
    <el-button @click="passMethods">点击,子组件传递值给父组件</el-button>
  </div>
</template>

<script>
export default {
  //接收从父组件传递的值
  props: ["child"],
  methods: {
    // 点击事件绑定方法
    passMethods() {
      this.$emit("passMethods", "修改父组件的msg");
    }
  }
};
</script>

结果展示:
在这里插入图片描述

兄弟组件间传值


兄弟组件的概念是什么?图中组件分为了三层,上面讲解的是 1 与 2 进行传值,那兄弟组件就是 3 和 3 之间传值。那我们是不是需要 3-2-1-2-3,这种方式进行传递呢?答案是可以实现,但也太麻烦了吧!

打个比方:老师当作父组件,学生当作子组件,考试的时候,学生的笔坏了,想向旁边的同学借笔,这时候,学生举手说:老师,我想借根笔。老师会拿旁边同学的笔给他。如果兄弟组件可以传值,就不用老师进行传递了,两个同学可以独立完成借笔这个操作。这也就是:观察者模式(也叫发布订阅模式/总线模式/Bus)

<body>
	<div id="root">
		<!-- 声明两个子组件 -->
		<child content='点赞收藏关注一条龙'></child>
		<child content='不可能只点赞收藏'></child>
		<script src="./vue.js"></script>
	</div>

	<script type="text/javascript">
		// 给每个vue实例添加 bus 属性,起到总线的作用
		Vue.prototype.bus = new Vue()
		// 声明全局子组件,名为 child
		Vue.component('child',{
			data:function(){
				return {
					childContent:this.content
				}
			},
			props:{
				content:String
			},
			// click事件绑定handleclick方法
			template:'<div @click="handleclick">{{childContent}}</div>',
			methods:{
				handleclick:function(){
					// 子组件向外触发 change 事件,携带content值
					this.bus.$emit('change',this.content)
				}
			},
			mounted:function(){
				var vm=this;
				// 组件挂载时,触发声明周期钩子mounted,用于监听 change 事件,接收传递的值
				this.bus.$on('change',function(msg){
					vm.childContent=msg;
				})
			}
		})
		//新建vue实例进行挂载
		var vm=new Vue({
			el:'#root'
		})
	</script>
</body>

结果展示:
在这里插入图片描述
我们来捋一遍整个过程如何实现的?:

我们点击文字,触发组件内的 handleclick 事件,handleclick 事件向总线触发 ‘change’ 事件,并将值传递过去。两个子组件被挂载完成时,都会执行 mounted 函数钩子,将各自组件保存在变量 vm 中,然后监听的 ‘change’ 事件被触发,将事件携带的值,传递给各自子组件的值。点击的文字的值传递过去,值不变;未点击的文字的值传递过去,改变了。这样,就实现了组件间传值。

不相关组件间传值


使用 vuex 进行传值,在 vue 项目中安装插件 vuex 插件。

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

至于如何使用 vuex 进行传值呢?

A页面向B页面传值。

  • A页面将值存储到 store.js 中
  • B从 store.js 中进行读取
//A页面将数据存储到 store.js 中
this.$store.commit("setAData", this.data); // 存储当前数据

//store.js 文件中进行接收
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

const store = new Vuex.Store({
	state: {
		//接收A页面传递的数据
		setAData(state, data) {
	      state.data = data;
	    },
	}
})

//B页面读取 store.js 中的数据
//写法一
computed:{
    getAData(){
      return this.$store.state.data 
    }
},

//写法二
import { mapState } from "vuex"; // 引入vuex用于将全局变量映射为页面变量
computed:{
	...mapState([	//解构到计算属性中
		'data'		//store.js 中的数据
	])
},

//写法三
import { mapState } from "vuex"; // 引入vuex用于将全局变量映射为页面变量
computed:{
	...mapState([	//解构到计算属性中
		Bdata:'data'		//重命名
	])
},

注意:

  • 官方建议我们将 this.$store.state.xxx 放到计算属性中使用,可以让代码看起来更优雅。
  • 每次读取 store.js 中的数据时,不需要用 this.$store.state.xxx 这种方式进行读取,使用写法二 …mapState 解构到当前页面的方式让代码更优雅

最后


以上为本人的一点学习记录与总结,如有错误,请指出,不胜感激。

猜你喜欢

转载自blog.csdn.net/weixin_42653522/article/details/106356242