vue 父组件给子组件传值,子组件修改了这个值,值有打印但是,但是视图没有更新。

完善下昨天的问题

子组件

clipboard.png

<popShop @resPopList="resPopList" :popList=popList :infoList=infoList></popShop>

子组件代码

<template>
    <div @click="hidePop" class="mask">
        <div @click="stopPop" class="pop-box">
            <div class="pop-img-box">
                <div class="pop-img-box_img">
                    <img :src="popList.PicImgUrl" alt="">
                </div>
                <div class="info-box">
                    <div>¥{{popList.Price * popList.num}}</div>
                    <div>{{popList.Name}}</div>
                </div>
            </div>
            <div class="chose-lists">
                <div v-for="(item,index) in infoList" @click="choseList(item.Name,item.Price,$event,item.ID)"
                     :class="index==0?'selColor':''">{{item.Name}}
                </div>
            </div>
            <div class="number-box">
                <ul class="btn-numbox">
                    <li><span class="number">数量</span></li>
                    <li class="input-box">
                        <ul class="count">
                            <li><span @click="numDown" class="num-jian">-</span></li>
                            <li><input disabled type="tel" maxlength="2" class="input-num" :value="popList.num"/>
                            </li>
                            <li><span @click="numUp" class="num-jia">+</span></li>
                        </ul>
                    </li>
                </ul>
            </div>
            <div class="pop-bottom_list">确定</div>
        </div>
    </div>
</template>
<script>
    export default {
        props: ['popList', 'infoList'],
        data() {
            return {}
        },
        methods: {
            hidePop: function () {
                $(".mask").hide();
            },
            stopPop: function (e) {
                e.stopPropagation();
            },
            numUp: function () {
                this.popList.num++;
                console.log(this.popList);
            },
            numDown: function () {
                if (this.popList.num <= 1) {
                    this.popList.num = 1;
                } else {
                    this.popList.num--;
                    console.log(this.popList);
                }
            },
            choseList: function (name, price, e, id) {
                $(e.srcElement).attr("class", "selColor").siblings().attr("class", "");
            },
        }
    }
</script>
<style>
    .mask {
        position: fixed;
        width: 100%;
        height: 100%;
        top: 0px;
        background: rgba(0, 0, 0, 0.4);
        overflow: hidden;
        z-index: 11;
        /*display: none;*/
    }

    /*弹出选项框*/
    .pop-bottom_list {
        color: #fff;
        padding: 10px 0;
        background-color: #ff4c4c;
        text-align: center;
    }

    .pop-box {
        width: 100%;
        position: absolute;
        bottom: 0;
        font-size: 17px;
        background-color: #fff;
    }

    .pop-img-box {
        padding: 0.8rem 0.8rem 0 0.8rem;
        margin-bottom: 0.5rem;
        position: relative;
    }

    .pop-img-box_img {
        border: 1px solid #e1e1e1;
        width: 5rem;
        height: 5rem;
        position: absolute;
        top: -50%;
    }

    .pop-img-box_img > img {
        width: 100%;
        height: 100%;
    }

    .number-box {
        padding: 0.8rem;
    }

    .input-box * {
        margin: 0;
        padding: 0;
        border: 0;
        outline: 0
    }

    .input-box {
        border: 1px solid #d6d7dc;
        border-radius: 1px;
    }

    .info-box {
        padding-left: 5.5rem;
    }

    .info-box > div:first-child {
        color: #ff4c4c;
    }

    .info-box > div:last-child {
        color: #7f8699;
    }

    .num-jian {
        border-right: 1px solid #d6d7dc;
    }

    .num-jia {
        border-left: 1px solid #d6d7dc;
    }

    .btn-numbox {
        overflow: hidden;
        /*margin-top: 20px;*/
    }

    .btn-numbox .number {
        font-size: 12px;
        margin-right: 0.5rem;
    }

    .btn-numbox li {
        float: left;
    }

    .btn-numbox .count {
        overflow: hidden;
    }

    .btn-numbox .count .num-jian,
    .input-num,
    .num-jia {
        display: inline-block;
        width: 28px;
        height: 28px;
        line-height: 28px;
        text-align: center;
        font-size: 18px;
        color: #999;
        cursor: pointer;
        position: relative;
        /*border: 1px solid #e6e6e6;*/
    }

    .btn-numbox .count .num-jia {
        margin-left: 1px;
    }

    .btn-numbox .count .input-num {
        width: 58px;
        height: 28px;
        color: #333;
        border-left: 0;
        border-right: 0;
    }

    .chose-lists {
        display: flex;
        flex-wrap: wrap;
        border-top: 1px solid #d6d7dc;
        padding: 0.5rem;
    }

    .chose-lists > div {
        background-color: #f3f5f9;
        border-radius: 2px;
        padding: 0 0.4rem;
        margin: 0.4rem 0 0 0.4rem;
    }

    .chose-lists .selColor {
        background-color: #ff4c4c;
        color: #fff;
    }
</style>

父组件代码

<template>
    <div class="padding-box">
        <div class="header rob-header">
            <a href="javascript:history.back()" class="back"></a>
            <span>订单详情</span>
        </div>
        <div class="detail-banner">
            <img :src="imgInfo.PicImgUrl" alt="">
        </div>
        <div class="good-info_box">
            <p class="good-info1">{{imgInfo.Name}}</p>
            <p class="good-info2">
                <span v-if="serType=='2'">¥{{imgInfo.Price}}</span>
                <span v-else>¥{{imgInfo.Price}}</span>
                <span v-show="serType=='0'">起</span>
            </p>
            <p class="good-info3">
                <span v-show="serType=='0'">上门服务</span>
                <span v-show="serType=='1'">预约定金</span>
                <span v-show="serType=='2'">上门测量</span>
            </p>
        </div>
        <div v-if="serType=='2'"><!--翻新网点信息-->
            <a href="javascript:void(0);" class="weui-media-box weui-media-box_appmsg detail-site">
                <div class="weui-media-box__hd">
                    <img class="weui-media-box__thumb" :src="SysOrg.PicImgUrl">
                </div>
                <div class="weui-media-box__bd">
                    <h4 class="weui-media-box__title">{{SysOrg.Name}}</h4>
                    <h4 class="weui-media-box__title">{{SysOrg.Phone}}</h4>
                </div>
            </a>
        </div>
        <div v-if="serType=='1'||serType=='0'" class="weui-cells margin_top">
            <div v-for="(item,index) in infoList" :class="index>7 ? hiddenList:''" class="weui-cell detail_weui-cell">
                <div class="weui-cell__bd">{{item.Name}}</div>
                <div class="weui-cell__ft">¥{{item.Price}}</div>
            </div>
            <div v-if="infoList.length>7" class="weui-cells good-info_more">
                <p>更多项目+</p>
            </div>
        </div>
        <div class="weui-cells margin_top">
            <div v-for="(item,index) in comment">
                <div class="weui-cell detail_weui-cell">
                    <div class="weui-cell__bd">评论({{item.total}})</div>
                    <div class="weui-cell__ft">
                        <span class="text_color">{{item.pre}}%</span>
                        <span>好评</span>
                    </div>
                </div>
                <div class="weui-cell detail_weui-cell">
                    <div class="weui-cell__bd dis_header">
                        <img :src="item.PhotoImgUrl" alt="">
                        <span>{{item.NickName}}</span>
                    </div>
                    <div class="weui-cell__ft">
                        <img v-for="n in item.JudgeStar" class="star-img" :src="starIcon" alt="">
                        <img v-for="n in 5-item.JudgeStar" class="star-img" :src="starIcon1" alt="">
                    </div>
                </div>
                <div class="weui-cell__bd over-star-val">{{item.Judge}}</div>
                <div class="weui-uploader__bd">
                    <ul class="weui-uploader__files dis_imgs">
                        <li v-for="(item,index) in item.Photos" class="weui-uploader__file"
                            :style="{'background-image':'url('+item+')'}"></li>
                    </ul>
                </div>
                <div class="weui-cells good-info_more" v-if="comment[0].total!=1">
                    <p><a>更多评论+</a></p>
                </div>
            </div>
        </div>
        <div class="img-detail">
            <div class="weui-loadmore weui-loadmore_line">
                <span class="weui-loadmore__tips">下面是商品详情</span>
            </div>
            <img class="detail-img_list" v-for="item in imgList" v-lazy="item" alt="">
        </div>
        <div class="bottom_bth_box">
            <div class="bottom_bth_box1">
                <div @click="goTel">联系客服</div>
            </div>
            <a class="bottom_bth_box2">
                <div v-if="serType=='1'">立即预约</div>
                <div v-if="serType=='0'">立即预约</div>
                <div v-if="serType=='2'">0元预约</div>
            </a>
        </div>
        <popShop :popList=popList :infoList=infoList></popShop>
    </div>
</template>
<script type="text/javascript">
    import {port,icon,common} from '../../util/config'
    import popShop from './order-detail-popShop.vue';
    export default {
        components: {
            popShop
        },
        data() {
            return {
                hiddenList: "hiddenList",
                imgInfo: '',
                serType: '',
                SysOrg: '',
                infoList: '',
                comment: '',
                imgList: '',
                popList:'',
                starIcon: icon.star,
                starIcon1: icon.star1
            }
        },
        methods: {
            evalImgList: function (data) {
                let imgList = data.split(/<img src="(\S*)" alt="" \/>/);
                for (let i = 0; i < imgList.length; i++) {
                    if (imgList[i] == "" || typeof(imgList[i]) == "undefined") {
                        imgList.splice(i, 1);
                        i = i - 1;
                    }
                }
                return imgList;
            },
            goTel: function () {
                $.actions({
                    actions: [{
                        text: common.tel,
                        onClick: function () {
                            window.location.href = 'tel://' + common.tel;
                        }
                    }]
                });
            },
        },
        created: function () {
            let that = this;
            let cityId = this.$route.query.cityId;
            let serType = this.$route.query.serType;
            let goodId = this.$route.query.goodId;
            let orgId = this.$route.query.orgId;
            this.serType = serType;
            port.GetProductDetailed.data.ID = goodId;
            port.GetProductDetailed.data.SysOrgID = orgId;
            let service = port.GetProductDetailed.name;
            let formData = JSON.stringify(port.GetProductDetailed.data);
            this.sendAjax.send(service, formData, cb);
            function cb(data) {
                if (that.serType == "0") {
                    ***//问题在这里,学识尚浅不知道怎么解释
                    //that.popList = data.Data.FiveList[0];
                    //that.popList.num = 1;
                   //该成这样就可以了
                   that.popList = {
                        num:1,
                        price:data.Data.FiveList[0].Price,
                        picImgUrl:data.Data.FiveList[0].PicImgUrl,
                        name:data.Data.FiveList[0].Name
                    };***
                }
                else if (that.serType == "2") {
                    that.SysOrg = data.Data.SysOrg[0]
                }
                that.imgInfo = data.Data.SrvService;
                that.infoList = data.Data.FiveList;
                that.comment = data.Data.comment;
                that.imgList = that.evalImgList(data.Data.SrvService.Content);
            }
        }
    }
</script>
<style>
    .detail-img_list[lazy=loading] {
        width: 60%;
        float: none;
    }

    .weui-loadmore_line .weui-loadmore__tips {
        background: #f4f4f4;
    }

    .detail-banner {
        height: 10rem;
        background-color: #e1e1e1;
        overflow: hidden;
    }

    .detail-banner img {
        width: 100%;
        vertical-align: middle;
    }

    .detail_weui-cell {
        padding: 5px 15px;
    }

    .star-img {
        width: 0.8rem;
        float: right;
    }

    .over-star-val {
        padding: 0 15px 15px 15px;
        font-size: 0.65rem;
    }

    .good-info_box {
        text-align: center;
        background-color: #fff;
        padding: 0.5rem 0
    }

    .good-info1 {
        font-size: 1rem;
    }

    .good-info2 {
        color: #ff4d4d;
        font-size: 0.9rem;
    }

    .good-info3 span {
        border: 1px solid #ff4d4d;
        padding: 0.1rem 0.5rem;
        font-size: 0.65rem;
        color: #ff4d4d;
        border-radius: 3px;
    }

    .margin_top {
        margin-top: 0.5rem;
    }

    .good-info_more {
        margin-top: 0;
    }

    .good-info_more > p {
        text-align: center;
        padding: 0.5rem;
    }

    .good-info_more > p > a {
        color: black;
    }

    .text_color {
        color: #ff4d4d
    }

    .dis_header img {
        vertical-align: middle;
        height: 1.2rem;
        width: 1.2rem;
        border-radius: 50%
    }

    .dis_header span {
        vertical-align: middle;
    }

    .dis_imgs {
        padding: 0 15px;
    }

    .bottom_bth_box {
        background-color: #fff;
        position: fixed;
        bottom: 0;
        display: flex;
        text-align: center;
        width: 100%;
        height: 50px;
    }

    .bottom_bth_box1 {
        width: 24%;
        margin: auto;
    }

    .bottom_bth_box1 > div {
        background-color: #fff;
        padding: 8px;
        border-radius: 3px;
        position: relative;
    }

    .bottom_bth_box1 > div:before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        border: 1px solid #d9d9d9;
        border-radius: 3px;
    }

    .bottom_bth_box2 {
        width: 63%;
        margin: auto;
    }

    .bottom_bth_box2 > div {
        background-color: #ff4c4c;
        padding: 8px;
        border-radius: 3px;
        color: #fff;
    }

    /*图片详情*/
    .img-detail {
        text-align: center;
    }

    .img-detail img {
        width: 100%;
        text-align: center;
        clear: both;
        float: left;
    }

    .hiddenList {
        display: none;
    }

    .input-box .count, .number-box .btn-numbox li {
        list-style: none;
    }

    .detail-site {
        margin-top: 0.5rem;
        background-color: #fff;
        padding: 0.5rem 0.75rem;
    }

    .dis_imgs .weui-uploader__file {
        width: 2.8rem;
        height: 2.8rem;
    }

</style>

clipboard.png

但是视图的值没有更新,还是默认的数量

clipboard.png

百度搜到$set方法 使用了 this.$set(this.popList.num, 2);但是报错了。以上是我描述的问题。

尝试解决

这里应该是我使用$set中的参数有误,感谢下回答者。应该是this.$set(this.popList,'num', 2);
但是我发现set并不能改变子组件视图中的值,代码如下

numUp: function () {
//    this.popList.num = parseInt(this.popList.num) + 1;
//    this.$emit('resPopList', this.popList);
    this.$set(this.popList,'num', parseInt(this.popList.num) + 1);
    console.log(this.popList.num);
    //打印出来值是有改变的
},

clipboard.png

但是视图中还是显示默认的数量

clipboard.png

求大神支个招刚接触vue不久还有很多要学习的。

最后发现问题是父组件中数据构造的问题
if (that.serType == "0") {

                ***//问题在这里,学识尚浅不知道怎么解释
                //that.popList = data.Data.FiveList[0];
                //that.popList.num = 1;
               //该成这样就可以了
               that.popList = {
                    num:1,
                    price:data.Data.FiveList[0].Price,
                    picImgUrl:data.Data.FiveList[0].PicImgUrl,
                    name:data.Data.FiveList[0].Name
                };***
            }
阅读 6.4k
4 个回答

没代码就只有猜了,如果popList是传过来的,想要改变popList.num的话

this.$set(this.popList,'num', 2);
<template>
  <div id="app">
          <myheader  :popList="popList"></myheader>
  </div>
</template>

<script>
    import Vue from 'vue'
    import myheader from './components/header/header'
    export default {
      name: 'app',
        data(){
            return{
                popList:{
                    num:0
                }
            }
        },
      components:{
          myheader
      }
    }
</script>

<style>

</style>
<template>
    <div class="header">
        <button @click="red">减</button>    
        <input disabled type="tel" maxlength="2" class="input-num" :value="popList.num"/>
        <button @click="add">加</button>    
    </div>
</template>

<script>
export default{
    name:"header",
     props: ['popList'],
    data(){
        return{
            
        }
    },
    methods:{
        red(){
            this.popList.num--;
        },
        add(){
            this.popList.num++;
        }
    }
}
</script>

<style scoped>

</style>

watch一下看是否真的变了

我没记错的话,官方是不建议你直接修改prop过来的值,需要用另外一个变量接受父组件传过来的值,再修改这个变量

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题