vue组件相关

组件通信


一、父向子传值用props

props:[‘传入的值名称’] ----props:[‘w’]
props:{传入值名称: 类型判断,}----props:[ w: Number]
完整写法
props: {
w: {
type: Number, //类型
required: true, //是否必须
default: 0, //默认值
validator(val) { //自定义校验
if (val) { return false }
},
},

<template>
  <div class="app">
    <BaseProgress :w="width"></BaseProgress>
  </div>
</template>

<script>
//子组件
import BaseProgress from './components/BaseProgress.vue'
export default {
  data() {
    return {
      width: 30,
    }
  },
  components: {
    BaseProgress,
  },
}
</script>

子组件

<template>
  <div class="base-progress">
    <div class="inner" :style="{ width: w + '%' }">
      <span>{{ w }}%</span>
    </div>
  </div>
</template>
<script>
export default {
  // 1.基础写法(类型校验)
  // props: {
  //   w: Number,
  // },

  // 2.完整写法(类型、默认值、非空、自定义校验)
  props: {
    w: {
      type: Number,
      required: true,
      default: 0,
      validator(val) {
        // console.log(val)
        if (val >= 100 || val <= 0) {
          console.error('传入的范围必须是0-100之间')
          return false
        } else {
          return true
        }
      },
    },
  },
}
</script>
<style scoped>
.base-progress {
  height: 26px;
  width: 400px;
  border-radius: 15px;
  background-color: #272425;
  border: 3px solid #272425;
  box-sizing: border-box;
  margin-bottom: 30px;
}
.inner {
  position: relative;
  background: #379bff;
  border-radius: 15px;
  height: 25px;
  box-sizing: border-box;
  left: -3px;
  top: -2px;
}
.inner span {
  position: absolute;
  right: 0;
  top: 26px;
}
</style>

data与props都可以给组件提供数据

props与data区别

1)data数据是自己内部数据,可以随便修改
2)props数是外部传入的,不能直接修改,要遵循单向数据流

父组件的props更新,会单向向下流动,影响到子组件
如果需要修改,需要使用$emit()通知父级修改


二、子向父传值用$emit()

子组件发送事件 this.$emit(‘父组件自定义事件名’,携带的参数)
父组件通过绑定自定义事件接收参数 <子组件名 @自定义事件=‘methods中处理方法’>
父组件通过在methods中的处理方法形参中接收传递过来的数据

 <template id="cala">
    <div>
       <BaseCount :count="count" @changeCount="handleChange"></BaseCount>
    </div>
  </template>
  <script>
import BaseCount from './components/BaseCount.vue'
export default {
  data() {
    return {
      count: 100
    }
  },
  components: {
    BaseCount
  },

  methods: {
    handleChange(newVal) {
      // console.log(newVal);
      this.count = newVal
    }
  }
}
</script>

子组件

<template>
  <div class="base-count">
    <button @click="handleSub">-</button>
    <span>{{ count }}</span>
    <button @click="handleAdd">+</button>
  </div>
</template>

<script>
export default {
  props: {
    count: {
      type: Number,
    },
  },
  methods: {
    handleSub() {
      this.$emit('changeCount', this.count - 1)
    },
    handleAdd() {
      this.$emit('changeCount', this.count + 1)
    },
  },
}
</script>

三、父访问子 $children或者$refs

1)使用 $children 数组类型

可以访问到子组件的数据,方法

  <template>
  <div class="app">
    <BaseProgress :w="width"></BaseProgress>
    <BaseCount :count="count" @changeCount="handleChange"></BaseCount>
    <button @click="btn">点击</button>
  </div>
</template>

<script>
import BaseProgress from './components/BaseProgress.vue'
import BaseCount from './components/BaseCount.vue'
export default {
  data() {
    return {
      width: 30,
      count: 100
    }
  },
  components: {
    BaseProgress,
    BaseCount
  },

  methods: {
    handleChange(newVal) {
      this.count = newVal
    },
    btn() {
      console.log(this.$children);
      //使用子组件方法
      this.$children[1].handleSub()
      //打印子组件数据
      console.log(this.$children[1].name);
    }
  }
}
</script>

在这里插入图片描述


2)$refs 对象类型,默认空对象{}

<template>
  <div class="app">
    <BaseProgress :w="width" ref="base"></BaseProgress>
    <button @click="btn">点击</button>
  </div>
</template>

<script>
import BaseProgress from './components/BaseProgress.vue'
export default {
  data() {
    return {
      width: 30
    }
  },
  components: {
    BaseProgress
  },

  methods: {
    btn() {
      console.log(this.$refs);
      // 可以直接访问到子组件数据
      console.log(this.$refs.base.uname);
    }
  }
}
</script>

在这里插入图片描述


四、子访问父 $parent$root

1)$parent 为父组件 VueComponent对象

子组件

 <template>
  <div class="base-progress">
    <button @click="btnclick">子组件访问父组件</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      uname: 'value',
    };
  },
  methods: {
    btnclick() {
      console.log(this.$parent);
    }
  }
}
</script>

在这里插入图片描述

2)$root即为根组件,为vue实例


五、非父子通信使用事件总线event bus 或者provide & inject

1)event bus 事件总线

非父子组件之间,进行简易消息传递。复杂场景要使用vuex

  1. 创建一个都能访问到的事件总线 (空 Vue 实例)
    在utils下新建EventBus.js
import Vue from 'vue';

const Bus = new Vue();

export default Bus
  1. A 组件(接收方),监听 Bus 实例的事件
    在created里面监听bus事件
    Bus.$on('事件名', (参数) => { })
    BaseA组件
<template>
  <div class="base-a">
    我是A组件(接受方)
    <p>{{msg}}</p>  
  </div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
  data() {
    return {
      msg: '',
    }
  },
  created() {
    Bus.$on('sendMsg', (msg) => {
      // console.log(msg)
      this.msg = msg
    })
  },
}
</script>

<style scoped>
.base-a {
  width: 200px;
  height: 200px;
  border: 3px solid #000;
  border-radius: 3px;
  margin: 10px;
}
</style>
  1. B 组件(发送方),触发 Bus 实例的事件
    Bus.$emit('事件名', 携带的参数)
    BaseB组件
<template>
  <div class="base-b">
    <div>我是B组件(发布方)</div>
    <button @click="sendMsgFn">发送消息</button>
  </div>
</template>

<script>
import Bus from '../utils/EventBus'
export default {
  methods: {
    sendMsgFn() {
      Bus.$emit('sendMsg', '今天天气不错,适合旅游')
    },
  },
}
</script>

<style scoped>
.base-b {
  width: 200px;
  height: 200px;
  border: 3px solid #000;
  border-radius: 3px;
  margin: 10px;
}
</style>

2)provide & inject

跨层级共享数据

  1. 父组件 provide 提供数据
    父组件
export default {
	provide(){
		return {
			str:this.str, //简单类型是非响应式的
			obj:this.obj //复杂类型是响应式的
		}
	},
	data(){
		return {
			str:'数据', 
			obj:{   
			 name:'aa',
			 age:19
			}
		}
	}
}
  1. 子/孙组件 inject 取值使用
    子/祖孙组件
export default {
  inject: ['str', 'obj'],
}

父组件中简单类型数据值发生变化,子/祖孙inject到的值不会响应式变化
父组件中复杂类型数据值发生变化,子/祖孙inject到的值响应式变化


六、通用方案 vuex

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值