组件间传值


一、父子组件间传值

  • 父传子:父组件传值给子组件 需要子组件用props接收值)
<template>
  <div class="app">
    <children name="jiangjiang" age="24" sex="男"></children>
  </div>
</template>

<template>
  <div class="app">
    <div>子组件接收到父组件的值:{{name}}{{age}}{{sex}}</div>
  </div>
</template>


// 简单声明接收
props:['name','age','sex']
// 接收的同时对数据进行类型限制
props:{
	name:String,
	age:Number,
	sex:String
}
// 接收的同时对数据进行类型限制 + 默认值的指定 + 必要性的限制
props:{
	name:{
		type:Stirng, // name 的类型是字符串
		required:true, // name 是必要的
		default:99
	}age:{
		type:Number,
		default:99 // 默认值
	}sex:{
		type:Stirng,
		required:true
	}
}
  • 子传父
<template>
  <div class="app">
    <child @btn="handelEmit" />
    父组件接收子组件的值:{{message}}
  </div>
</template>

methods: {
  handelEmit (val) {
    this.message = val	//父组件接收子组件的值
  }
},

<template>
  <div class="app">
    <button @click="btn">我是子组件的按钮 点击我将值传到现在的父组件中</button>
  </div>
</template>


methods: {
   btn () {
     this.$emit('btn', '123')//  参数一:参数名称,参数二为需要传递的值
   }
 },

二、非父子组件传值(provide、inject)

Provide/Inject用于非父子组件之间共享数据:比如有一些深度嵌套的组件,子组件想要获取父组件的部分内容;在这种情况下,如果我们仍然将props沿着组件链逐级传递下去,就会非常的麻烦;对于这种情况下,我们可以使用 Provide 和 Inject :
父组件存在Provide来提供数据。
子组件存在Inject来获取数据。
父组件 provide 与 data() 同级

// 一般用写法二
provide:{
	name:'jiangjiang',
	age:24
}
provide(){
	return{
		name:'jiangjiang',
		age:24
	}
}

子组件 inject 与 data() 同级

inject:['name','age']

如果Provide拿到的数据,是从data拿到的数据,此时该如何写呢?
如果我们修改了this.name的内容,那么使用的子组件是不会响应的:这是因为当我们修改了name之后,之前在provide中引入的 this.name 本身并不是响应式的。(可用computed实现)
父组件

data(){
	return{
		name:'jiangjiang
		//name: computed(() => this.name)
	}
},
provide(){
	return{
		name:this.name
	}
}

子组件

inject:['name']

三、兄弟组件传值(bus总线机制)

  • 接收数据:A组件想接收数据,则在A组件中给$bus 绑定自定义事件,事件的回调留在A组件自身
mounted(){
    this.$bus.$on('xxx',this.demo)
},
methods:{
	demo(data){.....}
}
  • 提供数据
this.$bus.$emit('xxx', 数据)

四、Vuex(状态管理工具)

专门在 Vue 中实现集中式(数据) 管理的一个 Vue 插件,对 Vue 应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间的通信方式,且适用于任意组件间的通信。适用于多个组件需要共享数据时。更改状态的唯一方法就是在mutaions里修改state,actions不能直接修改state(辅助函数—mapState,mapGetters,mapActions,mapMutations)

  • State --数据存贮
  • Getter --state的计算属性
  • Mutation --更改state中状态的逻辑 同步操作
  • Action --提交mutation 异步操作
  • Model --模块化

其中state和getters用来保存状态;mutations和actions用来改变状态;监听状态用的是Vue组件中的computed属性;module是用来组织整个应用的状态管理代码,使状态划分模块,更易于管理;辅助函数用来在监听状态时候简化代码,

关于store,需要先记住两点

  • store 中存储的状态是响应式的,当组件从store中读取状态时,如果store中的状态发生了改变,那么相应的组件也会得到更新;
  • 不能直接改变store中的状态。改变store中的状态的唯一途径是提交(commit)mutations。这样使
    得我们可以方便地跟踪每一个状态的变化。

机制:
在项目中我们要修改state状态的时候,我们需要使用this.$store.dispatch来触发actions中定义的方法,在actions里面定义的方法通过commit来调用mutations定义的方法来改变state状态。
在这里插入图片描述

state 基本数据,存储变量

const store = new Vuex.Store({
state: {
    name: 'jiangjiang',
    age:24,
    sex:'男'
  },
});

使用时
方法一:子组件能通过 this.$store 访问

this.$store.state.name

方法二:从vuex中按需导入mapstate函数(注意:当前组件需要的全局数据,映射为当前组件computed属性)

import { mapState } from "vuex";


computed:{
	// 借助 mapState 生成计算属性: name、age、sex(对象写法)
	...mapState({name:'name',age:'age',sex:'sex'})
	// 借助 mapState 生成计算属性: name、age、sex(数组写法)
	...mapState(['name','age','sex'])
}

Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 Mutation(两个形参:state是当前VueX对象中的state,
payload是该方法在被调用时传递参数使用的)

mutations:{
	//编辑
    edit(state,payload){
        //(1)直接调用
        state.name = 'wayne'
        //(2)传值调用
        state.name = payload
        //(3)传值对象调用
        state.name = payload.name
    }}
//页面通过this.$store.commit调用
//(1)直接调用
this.$store.commit('edit')
//(2)传值调用
this.$store.commit('edit','wayne')
//(3)传值对象调用
this.$store.commit('edit',{name:'wayne',sex:'男'})
//还可以这么写
this.$store.commit({
    type:'edit',
    payload:{
        name:'wayne',
        sex:'男'
    }
})
//使用mapMutations 辅助函数
import { mapMutations } from "vuex";
// 数组形式
methods:{
	...mapMutations(
		['edit']
	)
}
// 对象形式
methods:{
	...mapMutations(
		{'edit':'edit'}
	)
}

Getters加工state成员给外界类似于计算属性(两个默认参数:state 当前VueX对象中的状态对象,getters 当前getters对象)

getters:{
	nameInfo(state){
    	return "姓名:"+state.name
	},
   fullInfo(state,getters){
       return getters.nameInfo+'年龄:'+state.age
   }  
}
// 调用
this.$store.getters.fullInfo//姓名:jiangjiang 年龄:24

actions 专门放置异步操作,然后提交mutation去操作state(两个默认参数:context 上下文(相当于箭头函数中的this)对象,payload 挂载参数)

actions:{
   Edit(context,payload){
       //异步操作
       setTimeout(()=>{
           //提交mutations方法,修改state
           context.commit('edit',payload)
       },2000)
   }
 }
//在页面组件中调用:
this.$store.dispatch('Edit','wayne')

四、pinia

  1. 介绍

pinia是最新一代的轻量级状态管理插件,一个全新的用于 Vue 的状态管理库。下一个版本的 Vuex,也就是 Vuex 5.0。。按照尤雨溪的说法,vuex 将不再接受新的功能,建议将 Pinia 用于新的项目。

  1. 用法
    main.js引入
// main.js
 import { createApp } from 'vue'
 import App from './App.vue'
 // 导入构造函数
 import { createPinia } from 'pinia'
 // 实例化 Pinia
 const pinia = createPinia()
 // 创建Vue应用实例app
 const app = createApp(App)
 // 应用以插件形式挂载Pinia实例
 app.use(pinia)
 app.mount('#app')

src文件夹下新建store/index.js

// src/store/index.js
 // Store 是使用 defineStore() 定义的
import { defineStore } from 'pinia'

// 第一个参数是应用程序中 store 的唯一 id,是必要的,Pinia 使用它来将 store 连接到 devtools。
export const useCounterStore = defineStore('counter', {
// 类似组件的 data ,用来存储全局状态,推荐使用 完整类型推断的箭头函数(为了在服务端渲染的时候避免交叉请求导致数据污染)
  state: () => {
    return { 
    	count: 0,
    	name:'jiangjiang'
    }
  },
  // state: () => ({ count: 0 })
  // 类似于computed  用来封装计算属性 有缓存功能
  getters: {
    double: (state) => state.count * 2,
  },
  // 类似于methods  编辑业务逻辑
  actions: {
    increment() {
      this.count++
    },
  },
})

使用

// 引入store
import { useCounterStore } from '@/stores/counter'

export default {
  setup() {
    const counter = useCounterStore()

    counter.count++
    // 如果我们批量更改数据建议使用$patch方法,因为Pinia 的官方网站,已经明确表示 $patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。所以如果你是多条数据同时更新状态数据,推荐使用 $patch方式更新。
    counter.$patch({ count: counter.count + 1 })
    // or using an action instead
    counter.increment()
  },
}



// 也可以使用类似于vuex的mapState等方式引入
import { useCounterStore } from '@/stores/counter'

export default {
  computed: {
    // other computed properties
    // gives access to this.counterStore 
    ...mapStores(useCounterStore),
    // gives read access to this.count and this.double
    ...mapState(useCounterStore, ['count', 'double']),
  },
  methods: {
    // gives access to this.increment()
    ...mapActions(useCounterStore, ['increment']),
  },
}

修改state方法

1、counter.count++
2、counter.$dispatch({
	name:'jiangjiang1',
	count:1
}) // dispatch 传一个对象
3、counter.$dispatch((state)=>{
	state.name='jiangjiang1'
	state.count=1
})
4、counter.increment()

pinia 解构不具有响应式

import { storeToRefs } from 'pinia'

const { name,count } = storeToRefs(counter)
  1. Vuex 和 Pinia 的优缺点

Vuex的优点
● 支持调试功能,如时间旅行和编辑
● 适用于大型、高复杂度的Vue.js项目
Vuex的缺点
● 从 Vue 3 开始,getter 的结果不会像计算属性那样缓存
● Vuex 4有一些与类型安全相关的问题
Pinia的优点
● 完整的 TypeScript 支持:与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
● 极其轻巧(体积约 1KB)
● store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction 辅助函数,这在 Vuex 中很常见
● 支持多个Store
● 支持 Vue devtools、SSR 和 webpack 代码拆分
Pinia的缺点
● 不支持时间旅行和编辑等调试功能、

  1. pinia和vuex的区别

● 它没有mutation,他只有state,getters,action【同步、异步】使用他来修改state数据
● 他默认也是存入内存中,如果需要使用本地存储,在配置上比vuex麻烦一点
● 语法上比vuex更容易理解和使用,灵活。
● pinia没有modules配置,没一个独立的仓库都是definStore生成出来的
● state是一个对象返回一个对象和组件的data是一样的语法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在 React 中,有多种方式可以实现组件的值传递。以下是一些常见的方式: 1. Props(属性):通过在父组件中给子组件传递属性,子组件可以通过 props 对象来获取这些属性值。父组件中的属性变化会触发子组件的重新渲染。 2. State(状态):每个组件都有自己的状态对象,可以通过 setState 方法来更新状态并触发重新渲染。父组件可以通过 props 将状态值传递给子组件,并通过回调函数来修改父组件的状态。 3. Context(上下文):Context 提供了一种在组件树中共享数据的方式,可以在父组件中创建一个 Context 对象,并通过 Provider 组件将数据传递给子组件。子组件可以通过 Consumer 组件或 useContext 钩子来访问这些数据。 4. Redux 或其他状态管理库:使用 Redux 或其他状态管理库可以将应用的状态集中管理,并通过提供的 API 来进行状态的读取和更新。这样不同组件可以共享和传递状态,而不需要通过 props 层层传递。 5. 发布订阅模式或事件总线:可以使用发布订阅模式或事件总线来实现组件的解耦和通信。一个组件可以发布一个事件,其他组件可以订阅该事件并执行相应的操作。 这些是常见的组件传值方式,选择哪种方式取决于具体的场景和需求。在实际开发中,根据项目的规模和复杂度,选择合适的方式来进行组件的数据传递。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值