简述在Vue脚手架中,组件以及父子组件之间的传值

1、组件的定义

  • 局部组件:这里是一个三级地址组件
    • 首先看一下目录:在./src/components/下面新建立一个文件夹,此时命名为chinaAddress,在里面建立入口文件index.js,将你写好的组件通过import导入

                     

    • 在index.js里面进行全局注册组件;install是一个默认的方法
      import chinaAddress from './src/main';
      
      /* istanbul ignore next */
      chinaAddress.install = function(Vue) {
          Vue.component(chinaAddress.name, chinaAddress);
      };
      
      export default chinaAddress;
      View Code

      src里面的main.vue代码如下:

      <template>
          <div class="area">
              <el-select v-model="provinceCode" :placeholder="$t('message.common.province')" class="select" clearable @clear="clear">
                  <el-option v-for="item in provinceList" :key="item.value" :label="item.name" :value="item.value">
                  </el-option>
              </el-select>
              <div>&nbsp;{{$t('message.common.provinceOrDirectly')}}&nbsp;</div>
              <el-select v-model="cityCode" :placeholder="$t('message.common.city')" class="select">
                  <el-option v-for="item in cityList" :key="item.value" :label="item.name" :value="item.value">
                  </el-option>
              </el-select>
              <div>&nbsp;{{$t('message.common.city')}}&nbsp;</div>
              <el-select v-model="countryCode" :placeholder="$t('message.common.country')" class="select">
                  <el-option v-for="item in countryList" :key="item.value" :label="item.name" :value="item.value">
                  </el-option>
              </el-select>
              <div>&nbsp;{{$t('message.common.districtOrCountry')}}&nbsp;</div>
          </div>
      </template>
      <script>
      import chinaAddressData from './chinaAddressData'
      export default {
          name: 'chinaAddress',
          data() {
              return {
                  provinceCode: '', //省code
                  cityCode: '', //市code
                  countryCode: '', //县code
                  provinceList: [], //省表数据
                  cityList: [], //具体省下面市列表数据
                  countryList: [], //具体市下面县列表数据
                  addressCode: [], //组件内部省市县code数组
              }
          },
          props: {
              value: {
                  type: Array,
                  default () {
                      return []
                  }
              },
          },
          computed: {
      
          },
          components: {
      
          },
          watch: {
              value(newVal, oldVal) {
                  if (newVal.length) {
                      const [provinceCode, cityCode, countryCode] = newVal
                      this.provinceCode = provinceCode ? provinceCode : ''
                      this.cityCode = cityCode ? cityCode : ''
                      this.countryCode = countryCode ? countryCode : ''
                  }
              },
              provinceCode(newVal, oldVal) {
                  if (newVal) {
                      this.cityList = chinaAddressData.filter(val => val.parent === newVal)
                      this.cityCode = this.cityList[0].value
                  }
                  this.emitValueChange()
              },
              cityCode(newVal, oldVal) {
                  if (newVal) {
                      this.countryList = chinaAddressData.filter(val => val.parent === newVal)
                      this.countryCode = this.countryList[0].value
      
                  }
                  this.emitValueChange()
              },
              countryCode(newVal, oldVal) {
                  this.emitValueChange()
              }
          },
          mounted() {
      
          },
          created() {
              this.provinceList = chinaAddressData.filter(val => !val.parent)
          },
          methods: {
              emitValueChange() {
                  this.$nextTick(() => {
                      this.addressCode = [].concat(this.provinceCode, this.cityCode, this.countryCode).filter(val => val)
                      this.$emit('input', this.addressCode)
                      const addressInfo = {
                          provinceCode: '',
                          provinceName: '',
                          cityCode: '',
                          cityName: '',
                          countryCode: '',
                          countryName: '',
                      }
                      if (this.addressCode.length) {
                          const [provinceCode, cityCode, countryCode] = this.addressCode
                          addressInfo.provinceCode = provinceCode
                          addressInfo.cityCode = cityCode
                          addressInfo.countryCode = countryCode
                          addressInfo.provinceName = chinaAddressData.find(val => val.value === provinceCode)['name']
                          addressInfo.cityName = chinaAddressData.find(val => val.value === cityCode)['name']
                          addressInfo.countryName = chinaAddressData.find(val => val.value === countryCode)['name']
                      }
                      this.$emit('change', addressInfo)
                  })
              },
              clear() {
                  this.provinceCode = ''
                  this.cityCode = ''
                  this.countryCode = ''
                  this.emitValueChange()
              }
          },
      
      }
      </script>
      <style lang="scss" scoped>
      .area {
          width: 100%;
          display: flex;
         .select {
             width: 26%;
         }
      }
      </style>
      View Code

      js文件为:

    • 在main.js里面进行全局注册:(没有这一步,这是全局组件)
      import   chinaAddress from 'url';
      Vue.use(chinaAddress)
    • 在组件里面使用:
      <china-address v-model="addressCodeList" @change="addressChange"></china-address>
    • 局部组件的步骤如下:
      • 定义:
        var com = {
        //局部组件的定义,当名字为驼峰式命名myCom   写成<my-com></my-com>
           template: "<div>局部组件com{{msg}}</div>",
           data() {//每个组件的实例都有独立的数据
             return {
                msg: "hello",
                n: this.v
             };
           },
            methods: {}
        };
      • 注册:(在父组件中注册)
        components: {
            Header,
            com
         },
  • 全局组件:
    • 定义:
      Vue.component("组件的名字",{
          template:"模板的内容"(换行时用模板字符串``)//配置项
      })

2、数据传递方式(组件通信)

  • props传值
    • 父子组件之间的传值   
      • 父组件  -----> 子组件(参考资料https://www.cnblogs.com/Sky-Ice/p/9267192.html
        • 子组件不能修改父组件传递过来的值,因为数据时单向的(参考资料https://www.cnblogs.com/Sky-Ice/p/10456533.html
          在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。
          Prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得
          难以理解。 解决办法:  原理:将要更改的值,传递给父组件,在父组件中更改,再传递给子组件 步骤:  先将值传递给子组件,子组件 props 接收并使用,然后通过 $emit 广播一个事件给父组件,并将值一并传递,父组件 @子组件广播过来的事件,
          并定义一个方法,在该方法中,改变传递过来的值,父组件又会将值传递给子组件,这样就形成了一个闭环,问题得以解决
        • 传值:
          • 在父组件上用v-bind绑定要传递的属性,若没有v-bind,则属性的值始终是字符串  v-bind:v="msg"
            <template>
              <div id="example" style="margin-bottom:200px">
                我是首页
                <hr />这里是分界线
                <Header v-bind:v="msg"></Header>
              </div>
            </template>
            <script>
            import Header from "./header";
            export default {
              name: "example",
              data() {
                return {
                  msg: "我是你爸爸"
                };
              },
              components: {
                Header,//子组件
              },
              methods: {},
              mounted() {}
            };
            </script>
            View Code
          • 在子组件上用props属性进行接收:
            • 对象方式:(验证)
              props:{
                  v : {
                    type : String,//null表示可以为任意类型,Number为数值型,Object为一个对象,
                    default : 'hello',//不传之时指定默认值
                    required : true,//不传值则产生错误
              twoWay : true,//如果绑定类型不对将发出警告 } },
            • 数组方式:props : ["v"]
              <template>
                <div id="header">
                  <p>我是父组件传递过来的数据:{{v}}</p>
                </div>
              </template>
              <script>
              export default {
                props:["v"],
                name: "thesisHeader",
                data() {
                  return {
                    search: "", //搜索框内容
                  };
                },
                methods: {},
              };
              View Code
        • 传方法:
          • 在使用子组件时,根据传值的方式将方法进行绑定,:run="run";
          • 在子组件中,依旧使用props进行接收,this.run()运行;  
          • 子组件还可以用这种方式调用父组件的   this.$parent.方法/属性
        • 传父组件本身:
          • 在父组件中,使用子组件时,动态绑定this,即:home="home";
          • 子组件接收props:["home"];
          • 子组件使用:this.home.父组件的属性或者方法
      • 子组件 -----> 父组件(参考资料https://www.cnblogs.com/Sky-Ice/p/9289922.html
        • 步骤:
          • 依旧是父组件Home
            <template>
              <div>
                <div
                  id="example"
                  style="width:200px;height:200px;background:#ff0;font-size:25px;line-height:200px;text-align:center;margin:20px"
                >我是父组件</div>
                <Header></Header>
              </div>
            </template>
            <script>
            import Header from "./header";
            export default {
              name: "example",
              data() {
                return {
                  msg: "我是你爸爸"
                };
              },
              components: {
                Header //子组件
              },
              methods: {},
              mounted() {}
            };
            </script>
            View Code
            与子组件Header
            <template>
              <div id="header">
                <div
                  style="width:200px;height:200px;background:pink;font-size:25px;padding-top:100px;text-align:center;margin:20px"
                >我是子组件</div>
                <button @click="give">给父组件传值</button>
              </div>
            </template>
            <script>
            export default {
              name: "thesisHeader",
              data() {
                return {
                  msg: "爸爸,我是您的宝贝女儿啊!"
                };
              },
              methods: {
                give(){
                  
                }
              },
              mounted() {}
            };
            View Code
          • 子组件发送数据
             give() {
                  this.$emit("receive", { msg: this.msg });//$emit用来触发自定义事件,第一个参数是事件的名称,第二个参数是传递给监听事件的数据
             }
          • 父组件在使用子组件的地方进行监听
            <Header @receive="getData"></Header>
          • 接收数据,并进行处理
            getData(data){
                console.log(data)//{msg: "爸爸,我是您的宝贝女儿啊!"}
            }
        • 同理:传方法与自身都可以,像父组件给子组件的形式   当然,父组件还可以这么调用   this.$refs.名字.属性/方法
          //传方法 
          myMethod() { alert("我是属于子组件的方法"); }, give() { this.$emit("receive", { msg: this.msg, myMethod: this.myMethod }); }
          结果:{msg: "爸爸,我是您的宝贝女儿啊!", myMethod: ƒ} data.myMethod()执行
          //传组件本身
          give() { this.$emit("receive", { header: this }); }
          //父组件的接收处理方法
            getData(data){
               console.log(data.header)//子组件本身
               console.log(data.header.msg)//子组件属性
               data.header.myMethod()//子组件方法
            }
    • 父子组件通信的练习:
      • 父组件
        <template>
          <div>
            <div
              id="example"
              style="width:200px;height:200px;background:#ff0;font-size:25px;line-height:200px;text-align:center;margin:20px"
            >我是父组件</div>
            <Header @receive="getData" :message="msg"></Header>
          </div>
        </template>
        <script>
        import Header from "./header";
        export default {
          name: "example",
          data() {
            return {
              msg: "我是你爸爸"
            };
          },
          components: {
            Header //子组件
          },
          methods: {
            getData(data){
              this.msg = data.changeMessage;
            }
          },
          mounted() {}
        };
        View Code
      • 子组件
        <template>
          <div id="header">
            <div
              style="width:200px;height:200px;background:pink;font-size:25px;padding-top:100px;text-align:center;margin:20px"
            >我是子组件
            <p>爸爸说:{{message}}</p>
            </div>
            <button @click="give">给父组件传值</button>
          </div>
        </template>
        <script>
        export default {
          props:["message"],
          name: "thesisHeader",
          data() {
            return {
              msg: "爸爸,我是您的宝贝女儿啊!"
            };
          },
          methods: {
            myMethod() {
              alert("我是属于子组件的方法");
            },
            give() {
              this.$emit("receive", {changeMessage : "照顾好自己"});
            }
          },
          mounted() {}
        };
        </script>
        View Code
  • 组件通信
  • slot分发内容

3、混合

作用: 实现代码抽离复用
    eg:当创建了多个vue对象,都要用到一个方法,不应该将这个方法复制到每个对象的methods里面,应该采用'mixin'
    <script>
        var myMixin = {
            methods : {//公共方法
               test(){console.log(test)} 
            }
        }
        var vm1 = new Vue({
            el : "#box",
            mixins : [myMixin],
            template:{}
        })
        var vm2 = new Vue({...})//box2
    </script>

4、动态组件

转载于:https://www.cnblogs.com/wxh0929/p/11206180.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue,父组件与子组件之间传值有多种方式: 1. Props: 父组件通过props向子组件传递数据。在父组件使用子组件时,可以通过属性的形式将数据传递给子组件。子组件通过props选项来接收父组件传递的数据。例如: ```vue // 父组件 <template> <div> <child-component :message="parentMessage"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from parent' }; } }; </script> // 子组件 <template> <div> <p>{{ message }}</p> </div> </template> <script> export default { props: ['message'] }; </script> ``` 2. $emit: 子组件通过$emit方法向父组件发送事件,并携带需要传递的数据。父组件监听子组件触发的事件,并在事件处理函数获取子组件传递的数据。例如: ```vue // 父组件 <template> <div> <child-component @custom-event="handleCustomEvent"></child-component> <p>Message from child: {{ childMessage }}</p> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { childMessage: '' }; }, methods: { handleCustomEvent(message) { this.childMessage = message; } } }; </script> // 子组件 <template> <div> <button @click="sendMessage">Send Message to Parent</button> </div> </template> <script> export default { methods: { sendMessage() { this.$emit('custom-event', 'Hello from child'); } } }; </script> ``` 这些是Vue父子组件之间传值的两种常见方式,根据具体场景选择合适的方式进行数据传递。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值