**父组件是通过props属性给子组件通信的数据是单向流动 父—>子 **
子组件不能修改props 否则报错
实现步骤
1.子组件在props 创建一个属性,用于接收传输的值
2.父组件 引入子组件 - 注册子组件 - 引用子组件
3.父组件 在 子组件上 创建动态属性
4.将传递的值 赋值给 对应的动态属性
props 接收传值
<template>
<div>
<h2>{{msg}}h2>
<Son :msg="msg">Son>
div>
template>
<script>
// 1. 引入子组件
import Son from './Son'
//2.注册子组件
export default {
name: 'Parent',
data () {
return {
msg: '父组件',
}
},
components:{Son},
}
script>
<template>
<div>
<h2>子组件h2>
<div>{{msg}}给子组件传值div>
div>
template>
<script>
export default {
name: 'Son',
// 接收父组件传递的值
// 数组字符型
props:['msg'],
// 对象型
props:{
msg{
type:String,
required: true, // 非空
default: “子组件” // 默认值
}
}
}
script>
父组件 通过绑定自定义事件,接收子组件传递过来的参数
子组件 通过调用$emit 来触发父组件上的自定义事,从而实现传参
实现步骤
1.父组件在子组件标签上传入一个自定义事件
2.子组件通过$emit触发事件
3.$emit 第一个参数是事件名称,第二个参数是传入的参数
4.父组件事件函数中,接收传递的参数参与执行
<template>
<div>
<h2>父组件h2>
<Son @getData="getState">Son>
div>
template>
<script>
import Son from './Son'
export default {
name: 'Parens',
data () {
return {
msg: '父组件'
}
},
components:{Son},
methods:{
getState(state){
console.log(state) // 子组件 $emit 调用 父组件 getState 传递 state 参数
}
}
}
script>
<template>
<div >
<div>
子组件
div>
<button @click="setData">传值button>
div>
template>
<script>
export default {
name: "Son",
data(){
return {
state:"我是子组件"
}
},
methods:{
setData:function(){
this.$emit('getData',this.state)//触发getData方法,this.state 为向父组件传递的数据
}
}
}
script>
祖 --> 父孙
祖组件
<template>
<div>
<h2>我是父组价h2>
<div>我的数据有{{time}},{{name}},{{num}}div>
// 通过事件修改 num 值
<button @click="ReviseState">修改一下button>
<ComA />
div>
template>
<script>
import ComA from './components/ComA.vue'
export default {
name: 'VueApp',
data () {
return {
time: "2022-1-1",
name: "张三",
num: 30
};
},
methods: {
ReviseState () {
this.num++
}
},
components: {
ComA
},
provide () { // 传递给子孙组件 数据
return {
num: this.num,
time: this.time
}
}
};
script>
父组件
<template>
<div>
<h2>ComAh2>
<div>{{num}},{{time}}div>
<ComB />
div>
template>
<script>
import ComB from './ComB.vue'
export default {
name: 'VueComA',
inject: ['num', "time"], // 接收父组件传递的数据
components: {
ComB
}
};
script>
孙组件
<template>
<div>
<h2>ComBh2>
<div>我继承了{{num}},{{time}}div>
div>
template>
<script>
export default {
name: 'VueComB',
inject: ['num', "time"] // 接收祖组件传递的 数据
};
script>
祖组件修改了,子孙组件没有改变,这是因为在provide中引入数据本身并不是响应式的,所以我们可以使用一些响应式的API来完成这些功能,比如computed函数。而且在调用的时候,因为computed返回的是一个ref对象,我们要取出value属性来使用。
import {computed} from 'vue'
provide () { // 传递给子孙组件 数据
return {
num: computed(()=> this.num), // 使用 computed 使传递的数据具有响应式
time: this.time
}
}
全局事件总线可以用于非父子组件之间的通信,如与兄弟组件/兄弟组件的子组件进行通信。
先订阅 --> 再发布
全局传值
安装
npm install mitt
创建 mitt
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
组件A 传递数据 — 发布
<template>
<div>
<h2>ComAh2>
<div>{{num}}--{{uname}}div>
<button @click="setData">发送请求button>
<button @click="getnum">num++button>
<ComB />
div>
template>
<script>
import emitter from './mitt'
export default {
name: 'VueComA',
data () {
return {
num: 1,
uname: '张三'
}
},
methods: {
// 组件A 定义一个发起数据的事件
setData () {
// 发布
emitter.emit('setData', { num: this.num, name: this.uname })
},
getnum () {
this.num++
}
}
};
script>
组件A 接收数据 — 订阅
<template>
<div>
<h2>ComBh2>
<div>{{num}}--{{uname}}div>
div>
template>
<script>
import emitter from './mitt'
export default {
name: 'VueComB',
data () {
return {
num: 0,
uname: '李四'
}
},
created () {
// 接收传值数据 -- 订阅
emitter.on("setData", (data) => {
console.log(data);
this.uname = data.name
this.num = data.num
})
}
};
script>
全局传值
全局事件总线可以用于非父子组件之间的通信,如与兄弟组件/兄弟组件的子组件进行通信。
先订阅 --> 再发布
(与mitt 类似 – 不需要定义中间件)
安装
npm i pubsub-js --save-dev
组件A 传递数据 — 发布
import PubSub from 'pubsub-js'
// 发布
setData () {
PubSub.publish('setData', { num: this.num, name: this.uname })
},
组件B 接收数据 — 接收
<script>
import PubSub from 'pubsub-js'
// 订阅 第一个参数是 监听标识(_)占位符 第二个参数是传递参数
PubSub.subscribe("setData", (_, data) => {
console.log(data);
this.uname = data.name
this.num = data.num
})
}
script>
bus总线程 在vue3中已经废弃了
类似 mitt 和 pusbub
全局传值
new Vue({
render: h => h(App),
beforeCreate() {
//挂载全局事件总线 $bus
Vue.prototype.$bus = this;
},
}).$mount('#app');
组件A 传递数据 — 发布
this.$bus.$emit('setData', { num: this.num, name: this.uname })
组件B 接收数据 — 接收
this.$bus.$on('setData', (data) => {
this.uname = data.name
this.num = data.num
})
父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(“input”,val)自动修改v-model绑定的值
父传子 子改父
父组件 传递数据 – 不是响应式
<template>
<div>
<h2>我是父组价h2>
<div>{{num}}div>
<ComA v-model="num" />
<button @click="ReviseState">修改一下button> // 数据修改后 子组件不会有影响
div>
template>
<script>
import ComA from './components/ComA.vue'
export default {
name: 'VueApp',
data () {
return {
time: "2022-1-1",
name: "张三",
num: 30
};
},
methods: {
ReviseState () {
this.num++
}
},
components: {
ComA,
ComB
},
};
script>
子组件 接收数据 子组件可以修改父组件传递值
<template>
<div>
<h2>ComAh2
type="text"
v-model="num"
@change="setData">
div>
template>
<script>
export default {
name: 'VueComA',
data () {
return {
num: 0,
}
},
// 接收父级的传递的参数
props: {
value: Number
},
created () {
this.num = this.value
},
methods: {
setData () {
// 修改父级数据
this.$emit('input', this.num);
}
}
};
script>
<style lang="scss" scoped>
style>
全局传值
1--vuex注意事项:
不允许通过方法直接操作state
只能通过mutation 改变 state中的数据, 集中监听数据的实时变化
2--State 数据
$store.state.xxx 参数
通过 import { mapState } from 'vuex' 映射 接收 state的值
必须在 computed 中 ...mapState(['xxx']) xxx 字符串
3--Mutations 操作数据、
this.$store.commit('xxx', 参数)
import { mapMutations } from 'vuex' 映射 接收 mutations同步方法
必须在 methods 中 ...mapMutations(['xxx']) 带参数 调用时 xxx(参数)
4--Action 调用 Action 异步方法 触发 Mutations 操作 同步方法
this.$store.dispatch('xxx', 参数)
import { mapActions } from 'vuex' 映射 接收 Action异步方法
必须在 methods 中 ...mapActions(['xxx']) 带参数 调用时 xxx(参数)
5--Getters getters 对 state 进行监听
this.$store.getters.xxx
import { mapGetters } from 'vuex' 映射 接收 Getter 监听方法
必须在 computed 中 ...mapGetters(['xxx'])
6--modules 模块化
通过模块 私有化
模块调用 $store.state.模块名.参数
...mapState(['模块名'])
关于mutations 操作数据
1--定义state中数据操作方法
2--this.$store.commit(事件名称)
子传父 父控制子
<ComA ref="msg" /> -- 给子组件设置属性 ref=""
this.$refs.msg // 通过调用 $refs.xxx 获取到 子组件的组件实例 直接操作子组件订单方法和数据
利用路由跳转实现跨组件传值
- 传参
- router-link 路由导航
<router-link to = "/跳转路径/传入的参数"></router-link>
- 编程式导航
this.$router.push({
path:"/跳转路径/传入的参数"
})
- 接收参数
this.$route.params.xxx
- 传值
this.$router.push({
path:"/跳转路径",
params: { // 传参
name: '张三'
}
})
- 接收参数
this.$route.params.xxx
- 传值
this.$router.push({
path: '/跳转路径',
query: {
name: '张三'
}
})
- 接收参数
this.$route.query.xxx
利用缓存实现跨组件传值
全局传值
存储特效: 可以设置缓存时间,关闭浏览器 清除Cookie
大小特效: 存储大小 4kb左右 (20条左右信息)
服务通信: 用于携带 会话秘钥token值 等 剪短的字符串
特性: 数据保存在本地服务器 本地服务才能读取 可跨域 参与服务器交互
读写操作:
- 增: 生成cookie 需要键值对 才能生成多个
诺不然 会产生覆盖
document.cookie = 'aa=我是一个cookie'
cookie.setMaxAge(2000) // 设置 生命周期
document.cookie = 'aa=我是一个cookie;expires=+'new Date(Date.parse(new Date())+添加时间).+'
- 删:
将cookie 时间改成过去时
document.cookie = "name=; expires="+ 过去时间+";"
Cookies.remove('name');
- 改:
键值对对应 覆盖(修改)
document.cookie = "name=1" 添加 键值不存在
document.cookie = "name=2" 修改 键值相同
安全问题: 添加时 设置 HttpOnly 只允许指定域名读取
- cookies保存数据语法:
function setCookie(name,value)
{
var Days = 3;
var exp = new Date();
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
- cookies读取数据语法:
function getCookie(name)
{
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg))
return unescape(arr[2]);
else
return null;
}
- cookies删除数据语法:
function delCookie(name)
{
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval=getCookie(name);
if(cval!=null)
document.cookie= name + "="+cval+";expires="+exp.toGMTString();
}
传值
- 传入
document.cookie = '张三'
- 获取
name = document.cookie
存储特效: 关闭当前会话(页面),或者浏览器 清除session 仅保存在当前页面
大小特效: 存储大小 一般5M左右(根据浏览器不同决定)
特效: 数据保存 当前页面
读写操作:
- 增: 生成sessionStorage 需要键值对方式
sessionStorage.setItem("name","1")
- 删:
sessionStorage.removeItem("数据名") // 删除一条
sessionStorage.clear() // 删除全部
- 改:
sessionStorage.setItem("name","1") 添加 键值不存在
sessionStorage.setItem("name","2") 修改 键值相同
- 获:
sessionStorage.getItem("name")
传值
- 传入
sessionStorage.setItem("健名","值")
- 获取
sessionStorage.getItem("健名")
存储特效: 添加后 不手动清除,就不会消失
大小特效: 和 sessionStorage 类似
特性: 数据保存在本地内存
读写操作:
- 增:
localStorage.setItem("name","1");
localStorage.getItem("name")
- 删:
localStorage.removeItem("name")
localStorage.clear()
- 改:
localStorage.setItem("name","1"); // 增 键值不存在
localStorage.setItem("name","2"); // 改 键值相同
- 获:
localStorage.getItem("name")
传值
- 传入
localStorage.setItem("健名","值")
- 获取
localStorage.getItem("健名")
祖孙传值
父传子 -> 子级在自己的子组件上设置 v-bind=“$attr” --> 孙组件 接收父组件没有接收的值
祖组件
<ComA :num="num" :uname="uname" /> - 传递俩个参数
data () {
return {
uname: "张三",
num: 30
}
父组件
<ComB v-bind="$attrs" /> - 父组件设置 v-bind="$attrs" 将剩余参数传给下一个组件
props: {
num: Number
},
孙组件
props: {
uname: String, // 张三
num: Number // undefined 父组件拦截了 num值 所以子组件undf
},
孙祖传值
祖组件绑定自定义事件 --> 父组件 绑定自定义事件 v-on=“$listeners” --> 孙组件通过 $ $emit 触发祖组件自定义事件实现传值
祖组件
<ComA @event="event" /> -- 给子组件绑定自定义事件
methods: {
event (value) { // 接收孙组件的传值
console.log(value);
}
},
子组件
-- 设置 v-on="$listeners" 将祖组件的自定义函数传递给子组件
孙组件
<button @click="setData">按钮button> -- 触发祖组件事件 实现传值
methods: {
setData () {
this.$emit('event', '传参') // 传参
}
}
在vue实例原型中 存放数据