子组件向父组件传值

子组件触发自定义事件的方式:子组件触发一个自定义事件并传值,父组件监听事件执行方法并接受值,从而实现子组件调用父组件的方法并传值

uni-app父组件

<template>
    <view class="news">
        <news @itemClick="goDetail($event)"></news>
    </view>
</template>

<script>
    import news from '../../components/news-item/news-item.vue'
    export default {
        components: {news},    
        methods: {
            goDetail(id){
                console.log(id)
                uni.navigateTo({
                    url: '/pages/news-detail/news-detail?id=' + id
                })
            }
        },
    }
</script>

在父组件中通过$event来接收子组件传递过来数据,$event是固定的用法。

uni-app子组件:

<template>
    <view>
        <view class="news_item" v-for="(item,index) in news" :key="item.id" @click="goToDetail(item.id)">
            <image :src="item.img_url"></image>
            <view class="content">
                <view class="tit">
                    {{item.title}}
                </view>
                <view class="info">
                    <text>发表时间:{{item.add_time | formatDate}}</text>
                    <text>浏览:{{item.click}}</text>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        methods: {
            goToDetail(id){
                this.$emit('itemClick',id)
            }
        }
    }
</script>

点击的时候会触发$emit方法,这个方法名是固定的,并且需要携带一个参数,参数的名称就是所谓的自定义事件,参数的名称是自定义的。这个事件会传递给父组件,父组件需要监听这个事件,当子组件触发自定义事件时,会执行父组件中相应的动作。

vue子组件

handleClick(tab, event) {
        console.log(tab, event);
      },
      handleNodeClick(data) {
        console.log(data)
        //这里可以使用ajax请求后台,获取组织树的数据,转成json数组格式返回,result为返回的值
        //this.data=result.data;// 将子组件的值传递给父组件
        this.$emit('passResult',this.capitals)

      },

vue父组件

<statistic-analysis v-if="digitalMainIdx == 5"  @passResult="dealResult"></statistic-analysis>

dealResult方法:

dealResult(result){
        console.log(result)
      },

 

父组件向子组件传值:

1、父组件通过属性绑定的方式将值传递到子组件,子组件通过props方式接收

定义组件时,新增props属性,用于接收组件传过来的数据,它的值是一个数组,数组中可以包含很多的属性,这些属性都是从父组件传递过来的,传递过来之后就可以在模板中使用这个属性了。

props属性名规则:

如果在props中传递的名称采用了驼峰的形式,那么在模板中传递属性的时候,必须转化为短横线的形式,原因是DOM元素的属性无法区分大小写,如果我们传递的是驼峰形式就会有问题。但是字符串形式的模板没有这个限制。

 props属性值类型:字符串String,数值Number,布尔值Boolean,数组Array,对象Object

对于数值和布尔类型的数据来说,如果用v-bind进行绑定的话,在子组件中就可以得到对应类型的数据,如果不用v-bind绑定,则得到的都是字符串。

uni-app父组件:

<template>
    <view class="news">
        <news :news='news'></news>
    </view>
</template>

<script>
    import news from '../../components/news-item/news-item.vue'
    export default {
        components: {news},    
        data() {
            return {
                news: []
            }
        },
        methods: {
            async getNews(){
                const res = await this.$myRequest({url: '/api/getnewslist'})
                console.log(res)
                this.news = res.data.message
                
            }
          
        },
        onLoad() {
            this.getNews()
        }
    }
</script>

uni-app子组件:

<template>
    <view>
        <view class="news_item" v-for="(item,index) in news" :key="item.id" @click="goToDetail(item.id)">
            <image :src="item.img_url"></image>
            <view class="content">
                <view class="tit">
                    {{item.title}}
                </view>
                <view class="info">
                    <text>发表时间:{{item.add_time | formatDate}}</text>
                    <text>浏览:{{item.click}}</text>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        props: ['news']
    }
</script>

2、使用ref和$refs来实现给子组件传值

组件中使用ref和$refs来实现给子组件传值或者调用子组件的方法。在Vue中一般很少会用到直接操作DOM,但不可避免有时候需要用到,这时我们可以通过ref和$refs这两个来实现.

ref 被用来给子组件注册引用信息, 引用信息将会注册在父组件的 $refs 对象上,如果是在子组件上使用,引用就指向(子)组件的实例。

$refs 是一个对象,持有已注册过 ref 的所有的子组件

子组件代码如下:

<template>
    <div>
        <el-dialog :title="textMap[dialogStatus]+'工艺节点信息'" :visible.sync="dialogFormVisible" width="35%"
            @close="clearForm">
            <div>
                <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="180px" class="demo-ruleForm">
                    <el-form-item label="节点名称" prop="mesNodeNo">
                        <el-select v-model="ruleForm.mesNodeNo" placeholder="请选择" style="width:100%"
                            @change="getValue">
                            <el-option v-for="item in dataSetItemList" :key="item.itemCode" :label="item.itemName"
                                :value="item.itemCode">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="投入产出表关联方式" prop="relaInfo">
                        <el-select v-model="ruleForm.relaInfo" placeholder="请选择" style="width:100%">
                            <el-option v-for="item in dataSetItemList2" :key="item.itemCode" :label="item.itemName"
                                :value="item.itemCode">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="与上下级节点关联方式" prop="relaNext">
                        <el-select v-model="ruleForm.relaNext" placeholder="请选择" style="width:100%">
                            <el-option v-for="item in dataSetItemList2" :key="item.itemCode" :label="item.itemName"
                                :value="item.itemCode">
                            </el-option>
                        </el-select>
                    </el-form-item>
                </el-form>
            </div>
        </el-dialog>
    </div>
</template>

<script>

    export default {
        name: 'MesDialog',
        data() {
            return {
                //节点字典列表
                dataSetItemList: [],
                //投入产出字典列表
                dataSetItemList2: []

</script>

父组件代码如下:

<template>
    <div class="app-container">
        <node-config-dialog ref="nodeConfigDialog" @saveInfo="saveInfo"></node-config-dialog>
    </div>
</template>

<script>
    import NodeConfigDialog from './NodeConfigDialog'
    export default {
        name: 'NodeConfig',
        components: {
            NodeConfigDialog
        },
        data() {
            return {//数据集合代码,节点
                
            }
        },
        methods: {
            //查询字典数据
            getDataSetItems() {
                dataSet.getDataSetItemByDataSet({ dataCode: this.dataSetCode }).then(res => {
                    if (res.data.length != 1) {
                        this.$message.error("查询数据集合列表失败")
                        return
                    }
                    this.$refs.nodeConfigDialog.dataSetItemList = res.data[0].itemList
                }).catch(err => {
                    console.log(err)
                })
            },
              getDataSetItems2() {
                  dataSet.getDataSetItemByDataSet({ dataCode: this.dataSetCode2 }).then(res => {
                      if (res.data.length != 1) {
                          this.$message.error("查询数据集合列表失败")
                          return
                      }
                      this.$refs.nodeConfigDialog.dataSetItemList2 = res.data[0].itemList
                  }).catch(err => {
                      console.log(err)
                  })
              },
        }
    }
</script>

父组件通过$refs给子组件的属性赋值。也可以通过调用方法的方式传值:

父组件:

showNode() {
        this.$nextTick(() => {
          this.$refs[this.activeName][0].init(this.activeName, this.nodeData[this.activeName]);
        });
      },

子组件:

<script>
    export default {
      name: "nodeInfoOne",
      data() {
        return {
          caption: '',
          nodeList: []
        }
      },
      methods: {
        init(caption, data) {
          this.caption = caption;
          this.nodeList = data;
        }
      }
    }
</script>

特别注意:当父组件通过调用方法的方式给子组件传值时,需要在子组件的方法中将父组件传递过来的值复制一份后再赋值给子组件的属性,否则会发生子组件修改父组件的值的情况,案例如下:

父组件:

this.resultVisible = true
              setTimeout(function (){
                that.$refs["searchResult"].getData(that.hyTabs,data,that.listQuery); // 必须用that,否则为undefined
              },10);

子组件的getData方法:

getData(hyTabs,data,listQuery){this.listQuery = listQuery
    },

注意:getData方法中,直接将listQuery的值赋值给this.listQuery会导致修改子组件的值时,会修改父组件的值。故需要将listQuery复制一份再进行赋值。如下所示:

getData(hyTabs,data,listQuery){
      // 将listQuery复制一份后,再给this.listQuery,否则造成修改子组件的值的同时也修改了父组件的值。
      this.listQuery = Object.assign({}, listQuery)
    },

 

posted on 2020-12-30 09:11  周文豪  阅读(1197)  评论(0编辑  收藏  举报