VUE2 : 父子组件传值

3.4.父子组件传值

3.4.1.子组件 接收信息

父组件 显示子组件模板, 通过 props , $attrs 接值

3.4.1.1.子组件

通过 props 属性接到 父组件 传来值, 在子组件中可以通过 this 来使用这些信息

也可以 通过 $attrs 接收 没有被 props 声明的值

<template>
  <div>
    <input type="text" :value="value" />{{msg}} <br>
    a: {{a}} , other: {{$attrs}} <br>
  </div>
</template>
<script>
export default {
  name: "BaseComp1",
  props: {
    msg: {
      type: String,
      default: "数值"
    },
    a:{
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      value: this.msg + ", 子组件信息"
    }
  }
}
</script>
3.4.1.2.父组件

通过 msg 属性 向 子组件 传值

也可以通过 v-bind 一次性传递多组信息

<template>
  <div>
       <BaseComp1 msg="父组件传递的信息"   v-bind="{a:100, b:200, c:300}"   />
  </div>
</template>

<script>
import BaseComp1 from "./BaseComp1.vue"

export default {
  name: "index",
  components: {
    BaseComp1
  }
}
</script>

3.4.2.子组件 watch 监听

父组件 传递 动态信息 , 子组件 watch 监听信息

3.4.2.1.子组件

通过 watch 监听 父组件传来 msg 信息, 在回调函数中 修改 子组件中的信息

<template>
  <div>
    <input type="text"  :value="value"  />
  </div>
</template>
<script>
export default {
  name: "BaseComp2",
  props: {
    msg: {
      type: String,
      default: "数值"
    }
  },
  data() {
    return {
      value: this.msg + ", 子组件信息"
    }
  },
  watch: {
    msg: {
      handler(nv) {
        this.value = nv + ", 父信息改变了"
      }
    }
  },
}
</script>

3.4.2.2.父组件

向 子组件 传 msg 信息, 通过 按钮 修改msg, 被子组件watch监听

<template>
  <div>
    <BaseComp2 :msg="msg"  />{{msg}}
    <button @click="change">修改信息</button>
  </div>
</template>

<script>
import BaseComp2 from "./BaseComp2.vue"

export default {
  name: "index",
  components: {
    BaseComp2
  },
  data() {
    return {
      msg: "父组件msg",
    }
  },
  methods: {
    change(){
      this.msg = "父组件修改信息"
    }
  }
}
</script>

3.4.3.通过 props 传函数

父组件 传递 函数 , 子组件 调用函数回传值

3.4.3.1.子组件

接收 父组件传来 getData() 函数, 调用此函数 回传信息

<template>
  <div>
    <input type="text"  :value="value"  />
    <button @click="getData(value)">返回数据</button>
  </div>
</template>
<script>
export default {
  name: "BaseComp3",
  props: {
    msg: {
      type: String,
      default: "数值"
    },
    getData: {
      type: Function,
      default: () => {}
    }
  },
  data() {
    return {
      value: this.msg + ", 子组件信息"
    }
  }
}
</script>
3.4.3.2.父组件

向 子组件 传getData , 类型为函数, 子组件调用时 触发 监听函数 reData() 接收到值

<template>
  <div>
    <BaseComp3 :msg="msg"  :getData="reData"  />{{msg}} -{{reMsg }}
  </div>
</template>

<script>
import BaseComp3 from "./BaseComp3.vue"

export default {
  name: "index",
  components: {
    BaseComp3
  },
  data() {
    return {
      msg: "父组件msg",
    }
  },
  methods: {
  	reData(val){
      console.log( "返回信息:", val )
      this.reMsg = val
    }
  }
}
</script>

3.4.4.v-model绑定信息

子组件在 props 中使用value 接收信息 v-model的值, 通过 input 接收返回信息

页面 UI 组件最长用的方式

3.4.4.0.v-model的本质

v-model 实现双向绑定的原理 , 是 value 属性 及 input 事件

    <input :value="msg"  @input="msg=$event.target.value" /> <br>
3.4.4.1.子组件

通过 value 接收到 父组件 v-model 传来的信息

通过 v-model 双向绑定 childMsg, 当在子组件修改这个值时, 会被 watch 监听到

再 通过 this.$emit(‘input’, nv + “返回信息”); 通过 input 返回数据

<template>
  <input type="text"  v-model="childMsg"  />
</template>
<script>
export default {
  name: "BaseComp4",
  props: {
    value: {
      type: String,
      default: "数值"
    }
  },
  data() {
    return {
      childMsg: this.value + ", 子组件信息"
    }
  },
  watch: {
    childMsg: {
      handler(nv) {
        console.log(nv)
        this.$emit('input', nv + "返回信息");
      }
    }
  }
}
</script>
3.4.4.2.父组件

在 父 组件通过 v-model 双向绑定 msg , 子组件 通过 input 事件返回 子组件返回的信息

<template>
  <div>
    <h1>组件测试</h1>
    <h4> BaseComp4 :   子组件在 props 中使用value 接收信息 v-model的值  </h4>
    <h4> 通过  input 接收返回信息  </h4>
    <BaseComp4 v-model="msg"  /> {{msg}}
  
  </div>
</template>

<script>

import BaseComp4 from "./BaseComp4.vue"

export default {
  name: "index",
  components: {
    BaseComp4
  },
  data() {
    return {
      msg: "父组件msg",
    }
  }
}
</script>

3.4.5.textarea

3.4.5.1.子组件

将 input 换成 textarea 效果是一样

<template>
  <textarea   v-model="childMsg"  ></textarea>
</template>
<script>
export default {
  name: "BaseComp5",
  props: {
    value: {
      type: String,
      default: "数值"
    }
  },
  data() {
    return {
      childMsg: this.value + ", 子组件信息"
    }
  },
  watch: {
    childMsg: {
      handler(nv) {
        console.log(nv)
        this.$emit('input', nv + "返回信息");
      }
    }
  }
}
</script>
3.4.5.2.父组件
<template>
  <div>
    <BaseComp5  v-model="msg" /> {{msg}}
  </div>
</template>

<script>
import BaseComp5 from "./BaseComp5.vue"

export default {
  name: "index",
  components: {
    BaseComp5
  },
  data() {
    return {
      msg: "父组件msg",
    }
  }
}
</script>

3.4.6.select

3.4.6.1.子组件

接收到 value , options

下拉框 也可以 通过 input 事件, 返回信息

<template>
  <div>
    <select  v-model.number="selVal" >
      <option v-for="item in options" :key="item.value" :value="item.value" >{{item.label}}</option>
    </select>
  </div>
</template>
<script>
export default {
  name: "BaseComp6",
  props: {
    value: {
      type: Number,
      default: 0
    },
    options: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      selVal: this.value
    }
  },
  watch: {
    selVal: {
      handler(nv) {
        console.log(nv)
        this.$emit('input', nv);
      }
    }
  }
}
</script>
3.4.6.2.父组件
<template>
  <div>
    <BaseComp6  v-model="selVal" :options="checkOptions" /> {{selVal}}
  </div>
</template>

<script>
import BaseComp6 from "./BaseComp6.vue"
export default {
  name: "index",
  components: {
    BaseComp6
  },
  data() {
    return {
      selVal: 0,
      checkOptions: [
        {
          label: "选项0",
          value: "0"
        },
        {
          label: "选项1",
          value: "1"
        },
        {
          label: "选项2",
          value: "2"
        },
        {
          label: "选项3",
          value: "3"
        },
        {
          label: "选项4",
          value: "4"
        }
      ]
    }
  }
}
</script>


3.4.7.radio

3.4.7.1.子组件

单选框 也是通过 input 事件返回信息

<template>
  <div>
      <label v-for="item in options" :key="item.value" >
        <input type="radio" v-model.number="selVal" :value="item.value"   > {{item.label}}
      </label>
  </div>
</template>
<script>
export default {
  name: "BaseComp4",
  props: {
    value: {
      type: Number,
      default: 0
    },
    options: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      selVal: this.value
    }
  },
  watch: {
    selVal: {
      handler(nv) {
        console.log(nv)
        this.$emit('input', nv);
      }
    }
  }
}
</script>
3.4.7.2.父组件
<template>
  <div>
    <CheckComp1 v-model="selVal"  :options="checkOptions" /> {{selVal}}
  </div>
</template>

<script>
import CheckComp1 from "./CheckComp1.vue"

export default {
  name: "index",
  components: {
    CheckComp1
  },
  data() {
    return {
      selVal: 0,
      checkOptions: [
        {
          label: "选项0",
          value: "0"
        },
        {
          label: "选项1",
          value: "1"
        },
        {
          label: "选项2",
          value: "2"
        },
        {
          label: "选项3",
          value: "3"
        },
        {
          label: "选项4",
          value: "4"
        }
      ]
    }
  }
}
</script>

3.4.8.checkbox

3.4.9.1.子组件

用 value 接收到数组

<template>
  <div>
      <label v-for="item in options" :key="item.value" >
        <input type="checkbox" v-model.number="checkVals" :value="item.value"   > {{item.label}}
      </label>
  </div>
</template>
<script>
export default {
  name: "BaseComp4",
  props: {
    value: {
      type: Array,
      default: () => []
    },
    options: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      checkVals: this.value
    }
  },
  watch: {
    checkVals: {
      handler(nv) {
        console.log(nv)
        this.$emit('input', nv);
      }
    }
  }
}
</script>


3.4.8.2.父组件

通过 数组类型 selVals: [0,1], 向子组件 传值

<template>
  <div>
    <CheckComp2 v-model="selVals"  :options="checkOptions" /> {{selVals}}
  </div>
</template>

<script>
import CheckComp2 from "./CheckComp2.vue"

export default {
  name: "index",
  components: {
    CheckComp2
  },
  data() {
    return {
      selVals: [0,1],
      checkOptions: [
        {
          label: "选项0",
          value: "0"
        },
        {
          label: "选项1",
          value: "1"
        },
        {
          label: "选项2",
          value: "2"
        },
        {
          label: "选项3",
          value: "3"
        },
        {
          label: "选项4",
          value: "4"
        }
      ]
    }
  }

}
</script>

3.4.9.model 自定义

通过 model 在子组件中 自定义 接收值 ,及返回事件

3.4.9.1.子组件

通过 model 来 自定义 属性

<template>
  <input type="text"  v-model="childMsg"  />
</template>
<script>
export default {
  name: "BaseComp7",
  props: {
    // value: {
    //   type: String,
    //   default: "数值"
    // },
    customModelValue: {
      type: String,
      default: "数值"
    }
  },
  model: {
    prop: 'customModelValue', // 与父组件 v-model 绑定的 prop 名称
    event: 'updateCustomModelValue' // 触发更新父组件数据的事件名
  },
  data() {
    return {
      childMsg: this.customModelValue + ", 子组件信息"
    }
  },
  watch: {
    childMsg: {
      handler(nv) {
        console.log(nv)
        this.$emit('updateCustomModelValue', nv + "返回信息");
        // this.$emit('input', nv + "返回信息");
      }
    }
  }
}
</script>
3.4.9.2.父组件

父组件 使用 v-model:xxx 来指定 向 子组件 传递值

<template>
  <div>
    <BaseComp7  v-model:customModelValue="msg" /> {{msg}}
  </div>
</template>

<script>
import BaseComp7 from "./BaseComp7.vue"

export default {
  name: "index",
  components: {
    BaseComp7
  },
  data() {
    return {
      msg: "父组件msg",
    }
  }
}
</script>

3.4.10..sync 父子同步

3.4.10.1.子组件

使用 update:msg 向 父组件 同步数据

<template>
  <input type="text"  v-model="childMsg"  />
</template>
<script>
export default {
  name: "BaseComp4",
  props: {
    msg: {
      type: String,
      default: "数值"
    }
  },
  data() {
    return {
      childMsg: this.msg + ", 子组件信息"
    }
  },
  watch: {
    childMsg: {
      handler(nv) {
        console.log(nv)
        this.$emit('update:msg', nv + "返回信息");
      }
    }
  }
}
</script>
3.4.10.2.父组件

不再使用 v-model 来 监听子组件 回传数据, 而是 通过 .sync 来同步子组件返回的数据

<template>
  <div>
    <SyncComp1 :msg.sync="msg"  /> {{msg}}
  </div>
</template>

<script>

import SyncComp1 from "./SyncComp1.vue"

export default {
  name: "index",
  components: {
    SyncComp1
  },
  data() {
    return {
      msg: "父组件msg"
    }
  }
}
</script>

3.4.11.Click事件回传数据

3.4.11.1.子组件

使用 按钮 的 click事件 来 返回数据

<template>
  <div>
    <input type="text"  :value="childMsg"  />
    <button @click="returnData">点击</button>
  </div>

</template>
<script>
export default {
  name: "ClickComp1",
  props: {
    value: {
      type: String,
      default: "数值"
    }
  },
  data() {
    return {
      childMsg: this.value + ", 子组件信息"
    }
  },
  methods: {
    returnData() {
      this.$emit("input", this.childMsg + "返回信息")
    }
  }
}
</script>

3.4.11.2.父组件
<template>
  <div>
   <ClickComp1 v-model="msg"  /> {{msg}}
  </div>
</template>

<script>

import ClickComp1 from "./ClickComp1.vue"

export default {
  name: "index",
  components: {
    ClickComp1
  },
  data() {
    return {
      msg: "父组件msg",
    }
  }
}
</script>

3.4.12.computed监听数据

3.4.12.1.子组件

使用 computed 来 返回数据

<template>
  <div>
    <input type="text"  v-model="childMsg1"  />
    <input type="text"  v-model="childMsg2"  />
  </div>

</template>
<script>
export default {
  name: "BaseComp4",
  props: {
    value: {
      type: String,
      default: "数值"
    }
  },
  data() {
    return {
    }
  },
  computed: {
    childMsg1: {
      get() {
        return this.value+", 有子组件信息";
      },
      set(val) {
        this.$emit('input', val);
      }
    },
    childMsg2: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit('input', val);
      }
    }
  }
}
</script>
3.4.12.2.父组件
<template>
  <div>
    <ComputedComp1  v-model="msg"  /> {{msg}}
  </div>
</template>

<script>

import ComputedComp1 from "./ComputedComp1.vue"

export default {
  name: "index",
  components: {
    ComputedComp1
  },
  data() {
    return {
      msg: "父组件msg",
    }
  }
}
</script>

3.4.13.数据转汉字

3.4.13.1.子组件
<template>
  <div>
    <el-input v-model.number="num"></el-input>
    <span>{{ numStr }}</span>
  </div>
</template>

<script>
export default {
  name: "NumToString",
  props: {
    value: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      num: this.value,
      numStr:''
    }
  },
  watch: {
    num: {
      handler(nv) {
        this.numStr = this.numberToChinese(nv)
        this.$emit('input', nv);
      }
    }
  },
  methods: {
	// 转换函数
    numberToChinese(num) {
      const digits = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
      const units = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万'];

      // 处理负数和0的情况
      if (num === 0) return '零';
      if (num < 0) return '负' + numberToChinese(-num);

      let chineseNum = '';
      let currentUnitIndex = 0;
      num = num.toString().split('').reverse();

      for (let digit of num) {
        let digitStr = digits[digit];
        if (digit !== '0') {
          chineseNum = digitStr + units[currentUnitIndex] + chineseNum;
          // 遇到非零数字后,前面的零不再发音
          if (currentUnitIndex > 0 && digitStr !== '一' && chineseNum.charAt(chineseNum.length - 1) === '零') {
            chineseNum = chineseNum.slice(0, -1);
          }
        } else {
          if (chineseNum.length === 0 || chineseNum.charAt(chineseNum.length - 1) !== '零') {
            chineseNum += '零';
          }
        }
        if (digit !== '0' || (digit === '0' && currentUnitIndex % 4 === 0)) {
          currentUnitIndex++;
        }
      }
      // 格式化结果,移除不需要的零和单位
      chineseNum = chineseNum.replace(/零+([亿|万])/g, '$1').replace(/零+$/, '').replace(/^零+/, '');
      return chineseNum;
    }
  }
}
</script>

3.4.13.2.父组件
<NumToString v-model="num"  ></NumToString>

3.4.14.数值范围

3.4.14.1.子组件
<template>
  <div>
    <el-input-number v-model="range.min" placeholder="请输入最小值" controls-position="right" ></el-input-number>
    <span style="margin-left: 10px; margin-right:10px;">~</span>
    <el-input-number v-model="range.max" placeholder="请输入最大值" controls-position="right" ></el-input-number>
  </div>
</template>

<script>
export default {
  name: 'NumberRangeInput',
  props: {
    value: {
      type: Array,
      default: () => [null, null]
    }
  },
  data() {
    return {
      range: {
        min: this.value[0],
        max: this.value[1]
      }
    };
  },
  watch: {
    range: {
      handler(newValue) {
        this.$emit('input', [newValue.min, newValue.max]);
      },
      deep: true
    }
  }
};
</script>
3.4.14.2.父组件
  <NumberBetween v-model="rangeArray"  ></NumberBetween>

...

  rangeArray: [null, null],

3.4.15.$refs 找子组件

通过 $refs 找到子组件 调用 子组件函数

3.4.15.1.子组件

子组件 中定义 函数 接收val 参数

<template>
  <div>
    <input type="text"  :value="childMsg"  />
  </div>

</template>
<script>
export default {
  name: "ChildComp1",
  data() {
    return {
      childMsg: '子组件信息'
    }
  },
  methods: {
    setData(val) {
      this.childMsg =  "子组件信息" + val
    }
  }
}
</script>

3.4.15.2.父组件

在 父组件中 通过 $refs 找到指定的组件

<template>
  <div>
    <ChildComp1  ref="child1" />
    <button @click="$refs.child1.setData('父组件传递的信息')">修改子组件信息</button>
  </div>
</template>

<script>

import ChildComp1 from "./ChildComp1.vue"

export default {
  name: "index",
  components: {
    ChildComp1
  },

}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值