组件传值在我们vue的使用过程中一个很重要的功能,我们日常工作中需要使用各种形式的传值满足的我们的业务需求,传值的方法有很多,需要我们选择合适的.
1.props
props 是父传子中最常见的一种方式, 父组件用v-bind绑定数据
<hr />
<Children :count="count" />
子组件用props接受,可以是一个数据,也可以是一个对象详细描述传递参数
props: {
// count: Number 简写 或者下面对象形式
count: {
type: Number,
default: 0,
require: true
}
},
// props: ["count"],
注意vue是单向数据流,不能直接在子组件修改数据,需要用一个遍历接收,更改变量.
2.emit
子向父传值 子组件emit传递事件,2个参数 1个是事件名 一个是参数,如果有多个参数可以使用对象属性的形式
<template>这是子组件: <button @click="update">修改count的值为2</button></template>
<script setup>
import { defineEmits } from "vue";
const emit = defineEmits(["update"]);
const update = () => {
emit("update", 2);
};
</script>
父组件用v-on接受 绑定一个事件并执行
<template>
这是父组件: count:{{ count }}
<hr />
<Children @update="update" />
</template>
<script>
import Children from "./Son";
import { ref } from "vue";
export default {
name: "Father",
components: {
Children
},
setup() {
const count = ref(1);
const update = (num) => {
count.value = num;
};
return { count, update };
}
};
</script>
3.attrs $listeners
attrs和pros和props使用差不多 只是他不用声明可以直接使用,vue3在子组件中使用useAttrs引入
<template>
{{ attrs }}
</template>
<script setup>
import { useAttrs } from "vue";
const attrs = useAttrs();
</script>
父组件使用v-bind传值
<template>
这是父组件: count:{{ count }}
<hr />
<Children :count="count"/>
</template>
<script setup>
import Children from "./Son";
import { ref } from "vue";
const count = ref(1);
</script>
$listeners差不多就不详细写了 反向传值emit
4.ref传值
ref在父组件可以直接调用子组件暴露出来的变量或者方法
<template>
这是父组件: count:{{ count }} <button @click="getCount">获取子组件count</button>
<button @click="setCount">改变子组件count</button>
<hr />
<Children ref="refChildren" />
</template>
<script setup>
import Children from "./Son";
import { ref } from "vue";
const count = ref(1);
const refChildren = ref();
const getCount = () => {
console.log("子组件count:", refChildren.value.count2);
};
const setCount = () => {
refChildren.value.getCount(5);
};
</script>
子组件需要通过defineExpose暴露出去
<template>这是子组件:{{ count2 }}</template>
<script setup>
import { ref, defineExpose } from "vue";
const count2 = ref(2);
const getCount = (num) => {
count2.value = num;
};
defineExpose({
count2,
getCount
});
</script>
5.eventbus
事件总线 这个在vue3中已经被官方废除了,实现原理就是一个发布订阅模式.这里就用vue2来实现了. main.里面初始化
import Vue from 'vue';
Vue.prototype.$eventBus = new Vue();
在子组件2 触发事件 发布事件
<template>
<div class="xx-container">
这是子组件2:count:{{ count
}}<button @click="changeCount">修改子组件1的count</button>
</div>
</template>
<script>
export default {
props: {},
data() {
return {
count: 2
};
},
methods: {
changeCount() {
this.$eventBus.$emit('changeChildren1Count', 5);
}
}
};
</script>
在 子组件1中 监听事件
<template>
<div class="xx-container">这是子组件1:count:{{ count }}</div>
</template>
<script>
export default {
data() {
return {
count: 1
};
},
mounted() {
this.$eventBus.$on('changeChildren1Count', (num) => {
this.count = num;
});
}
};
</script>
<style lang="less" scoped></style>
6.provide,inject
子孙通信,当我们组件有多层嵌套且有多处使用,更改的时候可以使用provide,inject来通讯 父组件用provide来传递数据和方法
<template>
这是父组件: count:{{ count }}
<hr />
<Children />
</template>
<script setup>
import Children from "./Son";
import { ref, provide } from "vue";
const count = ref(1);
const changeCount = () => {
count.value = 5;
};
provide("getCount", count);
provide("changeCount", changeCount);
</script>
子孙组件用inject来接受数据和触发方法
<template>
这是父组件: count:{{ count }}
<hr />
<Children />
</template>
<script setup>
import Children from "./Son";
import { ref, provide } from "vue";
const count = ref(1);
const changeCount = () => {
count.value = 5;
};
provide("getCount", count);
provide("changeCount", changeCount);
</script>
7.children
vue2中可以直接通过this.parent和this.children访问父组件/子组件中的数据和方法 这个在vue3中废弃了 所以在这里用vue2实现 父组件
<template>
<div class="xx-container">
这是父组件:count:{{ count }}
<hr />
<Children1 />
</div>
</template>
<script>
import Children1 from './son1.vue';
export default {
components: {
Children1
},
data() {
return {
count: 1
};
},
methods: {
change() {
this.count = 4;
}
}
};
</script>
子组件this.$parent / this.children[0]
<template>
<div class="xx-container">
这是子组件 <button @click="change1">修改父组件count为4</button
><button @click="change2">修改父组件count为5</button>
<hr />
<Grandson />
</div>
</template>
<script>
import Grandson from './grandson.vue';
export default {
components: { Grandson },
data() {
return {
count: 2
};
},
methods: {
change1() {
this.$parent.change();
},
change2() {
this.$children[0].change();
}
}
};
</script>
孙组件
<template>
<div class="xx-container">这是孙组件:count:{{ count }}</div>
</template>
<script>
export default {
data() {
return {
count: 3
};
},
methods: {
change() {
this.count = 5;
}
}
};
</script>
8.全局vuex/pinia
全局的状态管理 store仓库里有5个模块 state,getter,mutation,action,module. 可以再组件内访问state的数据,或者调用mutation的同步方法,action的异步方法.具体的可以去看上一篇文字,这里就不做详细介绍了. juejin.cn/post/712986…
9.本地数据缓存sessionStorage,localStorage,indexDB
这里和vue没有直接关联,不属于vue特有的,谁都可以用.vue也可以用他来传递数据,但是要注意组件的加载顺序,如果还未存入获取不了 A组件:
<template>
这是父组件: count:{{ count }}
<hr />
<Children />
</template>
<script setup>
import Children from "./Son";
import { ref } from "vue";
const count = ref(1);
sessionStorage.setItem("count", count.value);
</script>
B组件
<template>
这是父组件: count:{{ count }}
<hr />
<Children />
</template>
<script setup>
import Children from "./Son";
import { ref } from "vue";
const count = ref(1);
sessionStorage.setItem("count", count.value);
</script>
vue可以使用vueuse库中的useLocalStorage,可以将LocalStorage中的数据封装成响应式的 vueuse.org/core/useloc…
10.路由传值
路由传值也是vue中通信方式中重要的一种,在页面跳转中传递重要的信息,有parmas和query2中形式,
query
query 传递一个对象,拼接在路由后面.参数可见.刷新页面不会消失 类似于get请求
params
params 传递一个对象,参数不可见,刷新页面就消失了,类似于post请求
具体的用法会在明天或者后天更新.这里就不做详细介绍了
11全局变量
vue2
在main.js中设置
Vue.prototype.$count = 1;
在组件中使用
<template>
<div class="xx-container">这是父组件:count:{{ count }}</div>
</template>
<script>
export default {
data() {
return {
count: this.$count
};
}
};
</script>
vue3
在vue3 mian.js中挂载到app.congif上
const app = createApp(App);
app.config.count = 1;
在组件中获取
<template>这是父组件: count:{{ count }}</template>
<script setup>
import { getCurrentInstance } from "vue";
const {
appContext: {
config: { count }
}
} = getCurrentInstance();
</script>
12在js中导出一个响应式数据和方法
在一个js文件中定义一个响应式数据
import { ref } from "vue";
export const count = ref(1);
在组件中引入数据
<template>这是父组件: count:{{ count }}</template>
<script setup>
import { count } from "./data";
</script>
这里改变数据的方法同理,还可以传入一个回调自己diy