一、Vue 2

一、基本结构

  • 子组件:
<template>
	<div>子组件</div>
</template>

<script>
  export default {
    // 命名
    name: "HelloWorld",
  }
</script>

<style>
</style>
  • 父组件:
<template>
  <div id="app">
  	<!-- 3.使用 -->
    <hello-world></hello-world>
  </div>
</template>

<script>
  // 1.导入
  import HelloWorld from './components/HelloWorld.vue'
  export default {
    name: 'App',
    // 2.注册
    components: {
      HelloWorld
    },
  }
</script>

<style>
</style>

建议大家遵守下 vue代码规范,不遵守的话,打包到线上时,可能会直接报错的哦!

代码规范示意图

分割图

二. 组件的传值

1、props | 父传子

例🌰一: 静态赋值

  • 子组件:
<template>
  <div class="helloWorld">
	<div>姓名:{{ name }}</div>
	<div>年龄:{{ age }}</div>
  </div>
</template>

<script>
  export default {
    props: ['name', 'age'],
  }
</script>

<style>
</style>
  • 父组件:
<template>
  <div id="app">
  	<!-- 3.使用 -->
    <hello-world name="阿狸" age="21"></hello-world>
  </div>
</template>

<script>
  // 1.导入
  import HelloWorld from './components/HelloWorld.vue'
  export default {
    name: 'App',
    // 2.注册
    components: {
      HelloWorld
    },
  }
</script>

<style>
</style>

页面显示:
例一


例🌰二: 动态赋值 ( 通过 v-bind )

  • 子组件:

核心代码:props:['hobby']

<template>
  <div class="helloWorld">
	<div>爱好:{{ hobby }}</div>
  </div>
</template>

<script>
  export default {
    props:['hobby'],
  },
  data() {
      return {
		hobby:'',
	  }
  },    
  created() {
	// 父组件的值:
	console.log( "父组件的值:", this.hobby )
  }
</script>

<style>
</style>
  • 父组件:

核心代码::hobby="要传递的值"

<template>
  <div id="app">
    <hello-world :hobby="hobby"></hello-world>
  </div>
</template>

<script>
  import HelloWorld from './components/HelloWorld.vue'
  export default {
    name: 'App',
    components: {
      HelloWorld
    },
    data() {
      return {
        hobby: '英雄联盟'
      }
    },
  }
</script>

<style>
</style>

页面显示:
例二


例🌰三: 类型校验

  • 子组件:
<template>
  <div class="helloWorld">
	<div>性别:{{ sex?'渣男':'渣女' }}</div>
    <div>爱人:{{ love.join(',') }}</div>
  </div>
</template>

<script>
  export default {
    name: "HelloWorld",
    props:['hobby'],
  }
</script>

<style>
</style>
  • 父组件:
<template>
  <div id="app">
  	<!-- 使用这个组件的时候, 数据的传递就不能乱写了哦 -->
    <hello-world msg="Welcome to Your Vue.js App" :sex=sex :love=love></hello-world>
  </div>
</template>

<script>
  import HelloWorld from './components/HelloWorld.vue'
  export default {
    name: 'App',
    components: {
      HelloWorld
    },
    props: {
      // 验证规则:
      sex: {
        type: Boolean,
        default: true
      },
      love: {
        type: Array,
        default: () => {
          return ['迪丽热巴', '鞠婧祎']
        }
      }
    },
    data() {
      return {
        // 数据的传递就不能乱写了
        sex: true,
        love: ['阿狸', '皎月']
      }
    },
  }
</script>

<style>
</style>

页面显示:
例三

props 验证
1. 可以直接为组件的 prop 属性指定基础的校验类型,从而防止组件的使用者为其绑定错误类型的数据
export default {
	props: {             // 支持的 8 中基础类型:
		propA: String,   // 字符串类型
		propB: Number,   // 数字类型
		propC: Boolean,  // 布尔值类型
		propD: Array,    // 数组类型
		propE: Object,   // 对象类型
		propF: Date,     // 日期类型
		propG: Function, // 函数类型
		propH: Symbol    // 符号类型
	}
}
2. 多个可能的类型

如果某个prop 属性值的类型不唯一,此时可以通过数组的形式,为其指定多个可能的类型:

export default {
	props: {
		propA: [String, Number],    // propA 属性的值可以是“字符串”或“数字”
	}
}
3. 必填项校验

如果组件的某个 prop 属性是必填项,必须让组件的使用者为其传递属性的值

export default {
	props: {
		propB: {
			type: String,
			required: true
		}
	}
}
4. 属性默认值

在封装组件时,可以为某个prop 属性 指定默认值

export default {
	props: {
		propC: {
			type: Number,
			default: 100
		}
	}
}
5. 自定义验证函数

在封装组件时,可以为 prop 属性指定自定义的验证函数,从而对 prop 属性的值进行更加精确的控制

export default {
	props: {
		propD: {
			validator(value) {
				return ['success', 'warning', 'danger'].indexOf(value) !== -1
			}
		}
	}
}

2、emit | 子传父

  • 子组件:

核心代码:this.$emit("reconfirm", 要传递的值 )

<template>
	<div @click="doIt"></div>
</template>

<script>
	export default {
		methods: {
      		doIt() {
        		// 传值给父组件:
        		this.$emit("reconfirm", "小弟弟!")
      		},
    	},
	}
</script>
  • 父组件:

核心代码:@reconfirm="reconfirm"

<template>
  <div>
    <hello-world @reconfirm="reconfirm"></hello-world>
  </div>
</template>

<script>
  import HelloWorld from './components/HelloWorld.vue'
  export default {
    components: {
      HelloWorld
    },
    methods:{
		// 获取子组件值:
		reconfirm(data) {
        	console.log("子组件值:", data)
      },
	}
  }
</script>

3、综合

父传子:用 props
子传父:用 emit

  • 父组件:
<developmentInfoEditDialog-switch
      :switch-val="switchVal"
      @reconfirm="reconfirm"
      ></developmentInfoEditDialog-switch>

<script>
	import PasswordDialog from './PasswordDialog'
	import DevelopmentInfoEditDialogSwitch from './DevelopmentInfoEditDialogSwitch'
	export default {
		components: {
			DevelopmentInfoEditDialogSwitch,
		},
		data(){
			switchVal:["我","是","你","爸","爸"],
		},
		methods: {
			// 获取子组件值:
      		reconfirm(data) {
        		console.log("子组件传过来的值:"+ data)
      		},
		}
    }
</script>
  • 子组件:
<script>
	export default {
    	// eslint-disable-next-line vue/require-prop-types
    	props: ['switchVal'],
    	created(){
			console.log("父组件传过来的值:" + this.switchVal)
		}
    	methods: {
			doIPCancel() {
	        	// 传值给父组件:
		        this.$emit('reconfirm', "我是小弟弟!")
	      	},
    },
    }
</script>

4、子传父时,父组件自带额外的参数

注意一下父组件中的 $event

子组件:

this.$emit("reconfirm", "哈哈", "嘿嘿");

父组件:

<developmentInfoEditDialog-switch
      @reconfirm="reconfirm($event, '嗷嗷~')"
      ></developmentInfoEditDialog-switch>

	// 获取子组件值:
	reconfirm(data, info) {
		console.log("子组件传过来的值:"+ data)
		console.log("父组件自带的值:"+ info)
	},

分割图

三、provide 和 inject

可以父子传值,还可以祖孙传值

1. 父节点通过 provide 共享数据

父节点的组件可以通过 provide 方法,对其子孙组件共享数据

export default {
	data() {
		return {
			// 1. 定义“父组件”要向“子孙组件”共享的数据	
			color: 'red'
		}
	},
	provide() { // 2. provide 函数 return 要共享的数据
		return {
			color: this.color,
		}
	}
}

2. 子孙节点通过inject接收数据

子孙节点可以使用 inject 数组,接收父级节点向下共享的数据

<template>
  <h5>子孙组件 {{color}}</h5>
</template>

<script>
export default {
    inject: ['color']
}
</script>

3. 父节点对外共享响应式的数据

父节点使用 provide 向下共享数据时,可以结合 computed 函数向下共享响应式的数据

import { computed } from 'vue'

export default {
	data() {
		return {
			color: 'red'
		}
	},
	provide() {
		return {
			// 使用 computed 函数,可以把要共享的数据包装为响应式的数据
			color: computed(()=> this.color)
		}
	}
}

4. 子孙节点使用响应式的数据

如果父级节点共享的是响应式的数据,则子孙节点必须以 .value 的形式进行使用

<template>
	<!-- 响应式的数据,必须以 .value 的形式进行使用 -->
	<h5>子孙组件 {{color.value}}</h5>
</template>

<script>
export default {
    inject: ['color']
}
</script>

ref

  • 父组件中用 this.$refs.子组件ref的值,等于进入子组件中并调用了子组件的 this
  • 子组件中用 this.$parent,等于进入父组件并调用了父组件的 this
  • 同一个组件中,可以给 DOM 节点加 ref='值',并通过this.$refs.值 操作此节点。

🌰子:
子组件:

<template>
  <div class="HelloWorld">
    <p ref="infoP_son">{{info}}</p>
    <button @click ="btnClick">子组件中获取父组件</button>
    <!-- 渲染父组件的信息到页面  -->
    <p>{{getInfo}}</p>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      info:"子组件",
      message:"来自子组件的数据",
      getInfo:''
    };
  },
  components: {},
  created() {},
  mounted() {},
  methods: {
    btnClick(){
      this.getInfo += this.$parent.message
    }
  }
};
</script>
<style lang='less' scoped>
.HelloWorld{
  background-color: red;
}
</style>

父组件:

<template>
  <div class="App">
    <p class="info" ref="infoP">{{info}}</p>
    <HelloWorld ref="HelloWorld"></HelloWorld>
    <button @click="btnClick">父组件中获取子组件</button>
    <!-- 渲染子组件的信息到页面  -->
    <p>{{getInfo}}</p>
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld";
export default {
  name: "App",
  data() {
    return { 
      info: "父组件",
      message:"来自父组件的信息",
      getInfo:''
    };
  },
  components: {
    HelloWorld
  },
  created() {},
  mounted() {
    // ref 疯狂操作 DOM
    this.$refs.infoP.style.color = 'pink'
    this.$refs.infoP.style.fontSize = '28px'
    this.$refs.HelloWorld.$refs.infoP_son.style.color = '#599eff'
    this.$refs.HelloWorld.$refs.infoP_son.style.fontSize = '28px'
  },
  methods: {
    btnClick() {
      // 获取子组件的信息
      this.getInfo += this.$refs.HelloWorld.message;
      window.console.log(this.$refs.HelloWorld.message);
    }
  }
};
</script>
<style lang='less' scoped>
.App {
  background-color: greenyellow;
}
</style>

开心
你可能需要:react 组件间的传值

开心

二、Vue 3

父传子 defineProps

需求:父组件传值给子组件;且在子组件调用父组件中的方法。

父组件:

<template>
  <UserDialog :objValue="objValue" @refresh="refresh"></UserDialog>
</template>

<script lang="ts" setup>
import { reactive } from "vue";
import UserDialog from "./components/userDialog.vue";

interface ITable{
  username: string;
  phone: string;
}

const objValue= reactive<ITable>({
  username: "",
  phone: "",
});

const refresh = (value: string) => {
	console.log("...", value)
}
</script>

子组件:

<template>
	<div>{{ objValue }}</div>
	<div @click="doRefresh">点击调用父组件的 refresh 方法</div>
</template>

<script lang="ts" setup>
import { ref, defineProps, toRefs, defineEmits } from "vue"; // 导入相关模块

const props = defineProps({ 
	objValue: {
		type: Object,
	    default: {},
	},
}); // 1.1.定义父组件传过来的数据的类型

const { objValue } = toRefs(props); // 1.2.接收父组件传过来的数据 objValue

const try = () => {
	const value: any = props.objValue; // 1.3.使用父组件传过来的数据 objValue
	console.log("...", value)
}

const emit = defineEmits(["refresh"]);

const doRefresh = () => {
  emit("refresh", "hello"); // 调用父组件的 refresh 方法,同时传参 hello
};
</script>

父传子孙 provide & inject

父组件:

<template>
	<div>{{ username }}</div>
	<div @click="add">改名啦</div>
</template>

<script lang="ts" setup>
import { ref, provide } from "vue";

const username = ref<string>("");
provide("username", username); // 传值给子组件

const add= () => {
  username.value = "小三";
};
</script>

子组件:

<template>
	<div>{{ username }}</div>
</template>

<script lang="ts" setup>
import { inject } from "vue";

const username : any = inject("username "); // 接收父级组件传的数据
</script>
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐