uniapp props、$ref、$emit、$parent、$child、$on、$set 是什么?

Dear 丶 2022-10-18 11:28 327阅读 0赞

举个例子来解释一下何为父组件,何为子组件?

举个例子来解释一下何为父组件,何为子组件?​​

20210605143156820.jpg

index.vue导入sunui-cell组件的时候,我们就称index.vue为父组件依次类推,在vue中只要能获取到组件的实例,那么就可以调用组件的属性或是方法进行操作

一、props(一般用来单向传值)

1. 何为单向传值?

即父组件传值给子组件(首次)但不能动态(再次)改变子组件现有的值,但我非要改呢? 通过watch监听或者通过$ref标识获取实例后修改以及使用v-modal,使用v-modal会存在不同步情况->使用.sync

2.props静态传值

子组件通过props选项来声明一个自定义的属性,然后父组件就可以在嵌套标签的时候,通过这个属性往子组件传递数据 - 引用脚本之家

67bfdc999eaf41b65c4b89c1e78656fa.png

2c309926409c11f830813e9b9cdcf8e4.png

3. props动态传值

通过v-bind绑定props的自定义的属性,传递去过的就不是静态的字符串了,它可以是一个表达式、布尔值、对象等等任何类型的值 - 引用脚本之家

9712c9242c4fe1494cdae27aa7fbaa5a.png

f9177b2b255f2c09c536e6846da0b130.png

4. props最适合传递数据,它并不能调用子组件里的属性和方法

二、$ref

1.不大适合传递数据

主要用来调用子组件里的属性和方法

b46f019fa69a00f95330c3b75b3d823c.png

通常是初始化页面(也就是视图层渲染完以后)才能调用,如果是初始化的时候调用,建议在mounted生命周期或者使用this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行(但我们首先得标识ref,相同组件ref的值如果重复会被后面的组件覆盖),如果不是初始化的话必须要等待它加载完以后才能够调用(this.nextTick)

876dc8b6bc6428183028574a74df1415.png

三、$emit

1. $emit 绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event监听并接收参数

5329375dfc94e76fb78daf55c594292a.png

四、$on(非父组件之间传值)

1.父组件需要导入A和B组件

  1. <template>
  2. <view class="content">
  3. <view style="padding: 12px 15px;">
  4. 点击hover效果
  5. </view>
  6. <onA></onA>
  7. <onB></onB>
  8. </view>
  9. </template>
  10. <script>
  11. import onA from '@/components/onA.vue';
  12. import onB from '@/components/onB.vue';
  13. export default {
  14. data() {
  15. return {
  16. title: 'Hello'
  17. }
  18. },
  19. components: {
  20. onA,
  21. onB
  22. },
  23. onLoad() {
  24. },
  25. mounted() {
  26. },
  27. methods: {
  28. }
  29. }
  30. </script>
  31. <style>
  32. .content {
  33. display: flex;
  34. flex-direction: column;
  35. align-items: center;
  36. justify-content: center;
  37. }
  38. .logo {
  39. height: 200rpx;
  40. width: 200rpx;
  41. margin-top: 200rpx;
  42. margin-left: auto;
  43. margin-right: auto;
  44. margin-bottom: 50rpx;
  45. }
  46. .text-area {
  47. display: flex;
  48. justify-content: center;
  49. }
  50. .title {
  51. font-size: 36rpx;
  52. color: #8f8f94;
  53. }
  54. </style>

2. onA组件

  1. <template>
  2. <view>
  3. <button type="primary" @click="onSend">传值给onB组件</button>
  4. </view>
  5. </template>
  6. <script>
  7. import bridge from '@/utils/bridge.js';
  8. export default {
  9. data() {
  10. return {
  11. msg: 'hello,onB'
  12. };
  13. },
  14. methods: {
  15. onSend() {
  16. bridge.$emit('receiveA', this.msg);
  17. }
  18. },
  19. mounted() {
  20. bridge.$on('receiveB', (val) => {
  21. console.log('我是onA组件,接收来自onB的值:', val);
  22. });
  23. }
  24. }
  25. </script>
  26. <style>
  27. </style>

3.onB组件

  1. <template>
  2. <view>
  3. <button type="primary" @click="onSend">传值给onA组件</button>
  4. </view>
  5. </template>
  6. <script>
  7. import bridge from '@/utils/bridge.js';
  8. export default {
  9. data() {
  10. return {
  11. msg: 'hello,onA'
  12. };
  13. },
  14. methods: {
  15. onSend() {
  16. bridge.$emit('receiveB', this.msg);
  17. }
  18. },
  19. mounted() {
  20. bridge.$on('receiveA', (val) => {
  21. console.log('我是onB组件,接收来自onA的值:', val);
  22. });
  23. }
  24. }
  25. </script>
  26. <style>
  27. </style>

五、$parent(用于子组件获取父组件实例) - 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己

4192bc57f21a95a8a06c8c905f6aaaa0.png

六、$child - 当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源

  1. <template>
  2. <view class="content">
  3. <view style="padding: 12px 15px;">
  4. 点击hover效果
  5. </view>
  6. <onA></onA>
  7. <onB></onB>
  8. </view>
  9. </template>
  10. <script>
  11. import onA from '@/components/onA.vue';
  12. import onB from '@/components/onB.vue';
  13. export default {
  14. data() {
  15. return {
  16. title: 'Hello'
  17. }
  18. },
  19. components: {
  20. onA,
  21. onB
  22. },
  23. onLoad() {
  24. },
  25. mounted() {
  26. console.log(this.$root.$children[0].$children[0]._data);
  27. console.log(this.$root.$children[0].$children[1]._data.msg);
  28. console.log(this.$root.$children[0].$children[2]._data.msg);
  29. },
  30. methods: {
  31. }
  32. }
  33. </script>
  34. <style>
  35. .content {
  36. display: flex;
  37. flex-direction: column;
  38. align-items: center;
  39. justify-content: center;
  40. }
  41. .logo {
  42. height: 200rpx;
  43. width: 200rpx;
  44. margin-top: 200rpx;
  45. margin-left: auto;
  46. margin-right: auto;
  47. margin-bottom: 50rpx;
  48. }
  49. .text-area {
  50. display: flex;
  51. justify-content: center;
  52. }
  53. .title {
  54. font-size: 36rpx;
  55. color: #8f8f94;
  56. }
  57. </style>

七、$set - **在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的**

1.运行这个示例时,我们发现对象新增的属性(e)是不会更新

  1. <template>
  2. <view>
  3. <view @click="addd(obj)">点击增加1:{
  4. {obj.d}}</view>
  5. <view @click="adde(obj)">点击增加2:{
  6. {obj.e}}</view>
  7. </view>
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return {
  13. obj: {}
  14. }
  15. },
  16. mounted() {
  17. // 原有的
  18. this.obj = {
  19. d: 0
  20. };
  21. // 新增的对象.e
  22. this.obj.e = 0;
  23. console.log('after--', this.obj);
  24. },
  25. methods: {
  26. addd(item) {
  27. item.d = item.d + 1;
  28. console.log('item--1', item);
  29. },
  30. adde(item) {
  31. item.e = item.e + 1;
  32. // this.$forceUpdate();
  33. console.log('item--2', item);
  34. }
  35. }
  36. }
  37. </script>
  1. 我们有两种解决方案,一种是利用this.$set或者this.$foreUpdate();让它渲染到视图层 - 代码引用简书:https://www.jianshu.com/p/71b1807b1815

9f89485ebcbafb6165b28635913742d8.png

  1. <template>
  2. <view>
  3. <view @click="addd(obj)">点击增加1:{
  4. {obj.d}}</view>
  5. <view @click="adde(obj)">点击增加2:{
  6. {obj.e}}</view>
  7. </view>
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return {
  13. obj: {}
  14. }
  15. },
  16. mounted() {
  17. // 原有的
  18. this.obj = {
  19. d: 0
  20. };
  21. // 新增的对象.e
  22. // this.obj.e = 0;
  23. this.$set(this.obj, 'e', 0);
  24. console.log('after--', this.obj);
  25. },
  26. methods: {
  27. addd(item) {
  28. item.d = item.d + 1;
  29. console.log('item--1', item);
  30. },
  31. adde(item) {
  32. item.e = item.e + 1;
  33. // this.$forceUpdate();
  34. console.log('item--2', item);
  35. }
  36. }
  37. }
  38. </script>

理清一下已经使用过的vue实例,可能会再次更新(-.-)

发表评论

表情:
评论列表 (有 0 条评论,327人围观)

还没有评论,来说两句吧...

相关阅读

    相关 什么uniapp----分包

    分包(Subpackage)是指在UniApp中将应用程序的代码和资源分割成多个部分,使得应用在运行时可以按需下载和加载这些部分,从而优化应用的启动速度和性能。 下面我将通过

    相关 什么uniapp

    初来乍到,一个小白,讲述一些最近了解uniapp后的一些心得,后面随着自己学习的深入,会陆续增添内容。 uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开