1. 父传子
1. props
**父组件是通过props属性给子组件通信的数据是单向流动 父—>子 **
子组件不能修改props 否则报错
实现步骤
1.子组件在props 创建一个属性,用于接收传输的值
2.父组件 引入子组件 - 注册子组件 - 引用子组件
3.父组件 在 子组件上 创建动态属性
4.将传递的值 赋值给 对应的动态属性
props 接收传值
- 父组件
<template>
<div>
<h2>{{msg}}</h2>
<!-- 3.自定义动态属性给子组件传值-->
<Son :msg="msg"></Son>
</div>
</template>
<script>
// 1. 引入子组件
import Son from './Son'
//2.注册子组件
export default {
name: 'Parent',
data () {
return {
msg: '父组件',
}
},
components:{Son},
}
</script>
- 子组件
- props 有三种接收数据的方式
-
- 数组字符型 [‘msg’,‘num’]
- 对象型 { msg{ type:String,required: true } }
<template>
<div>
<h2>子组件</h2>
<div>{{msg}}给子组件传值</div>
</div>
</template>
<script>
export default {
name: 'Son',
// 接收父组件传递的值
// 数组字符型
props:['msg'],
// 对象型
props:{
msg{
type:String,
required: true, // 非空
default: “子组件” // 默认值
}
}
}
</script>
2. 子传父
父组件 通过绑定自定义事件,接收子组件传递过来的参数
子组件 通过调用$emit 来触发父组件上的自定义事,从而实现传参
实现步骤
1.父组件在子组件标签上传入一个自定义事件
2.子组件通过$emit触发事件
3.$emit 第一个参数是事件名称,第二个参数是传入的参数
4.父组件事件函数中,接收传递的参数参与执行
- 父组件
<template>
<div>
<h2>父组件</h2>
<Son @getData="getState"></Son>
<!-- 监听子组件触发的getData事件,然后调用getState方法 -->
</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>
3. 非父子
1. provide 和 inject
祖 --> 父孙
祖组件
<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>ComA</h2>
<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>ComB</h2>
<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
}
}
2. mitt 库
全局事件总线可以用于非父子组件之间的通信,如与兄弟组件/兄弟组件的子组件进行通信。
先订阅 --> 再发布
全局传值
-
安装
npm install mitt
-
创建 mitt
import mitt from 'mitt'; const emitter = mitt(); export default emitter;
-
组件A 传递数据 — 发布
<template> <div> <h2>ComA</h2> <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>ComB</h2> <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>
3. pusbub 库
全局传值
全局事件总线可以用于非父子组件之间的通信,如与兄弟组件/兄弟组件的子组件进行通信。
先订阅 --> 再发布
(与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>
4. Bus 总线程
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 })
5. v-model
父组件通过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>ComA</h2 <input 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>
6. vuex 全局状态管理
全局传值
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(事件名称)
7. ref
子传父 父控制子
- 父组件
<ComA ref="msg" /> -- 给子组件设置属性 ref=""
this.$refs.msg // 通过调用 $refs.xxx 获取到 子组件的组件实例 直接操作子组件订单方法和数据
8. 路由(Route)传值
利用路由跳转实现跨组件传值
1. 动态传参
- 传参
- router-link 路由导航
<router-link to = "/跳转路径/传入的参数"></router-link>
- 编程式导航
this.$router.push({
path:"/跳转路径/传入的参数"
})
- 接收参数
this.$route.params.xxx
2. params 传值
- 传值
this.$router.push({
path:"/跳转路径",
params: { // 传参
name: '张三'
}
})
- 接收参数
this.$route.params.xxx
3. query传值
- 传值
this.$router.push({
path: '/跳转路径',
query: {
name: '张三'
}
})
- 接收参数
this.$route.query.xxx
9. 缓存
利用缓存实现跨组件传值
全局传值
1. Cookie
- 特性
存储特效: 可以设置缓存时间,关闭浏览器 清除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
2. sessionStorage
- 特性
存储特效: 关闭当前会话(页面),或者浏览器 清除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("健名")
3. localStorage
- 特性
存储特效: 添加后 不手动清除,就不会消失
大小特效: 和 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("健名")
10. $attr
祖孙传值
父传子 -> 子级在自己的子组件上设置 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 },
11. $listeners
孙祖传值
祖组件绑定自定义事件 --> 父组件 绑定自定义事件 v-on=“$listeners” --> 孙组件通过 $ $emit 触发祖组件自定义事件实现传值
-
祖组件
<ComA @event="event" /> -- 给子组件绑定自定义事件 methods: { event (value) { // 接收孙组件的传值 console.log(value); } },
-
子组件
<ComB v-on="$listeners" /> -- 设置 v-on="$listeners" 将祖组件的自定义函数传递给子组件
-
孙组件
<button @click="setData">按钮</button> -- 触发祖组件事件 实现传值 methods: { setData () { this.$emit('event', '传参') // 传参 } }
12. 设置全局变量
在vue实例原型中 存放数据