Javascript 两个子组件使用vue.js将数据传递给同一父组件

Javascript 两个子组件使用vue.js将数据传递给同一父组件,javascript,vue.js,parent-child,emit,Javascript,Vue.js,Parent Child,Emit,我现在使用的是一个api旅行数据,我想用分页来显示它,同时用首选的排序方法来显示数据。我试图将所有内容分为三个部分: 分页--用于页面的按钮 sortbar——用于对移动数据进行排序 视图——根据上面的两个组件显示相应的数据。例如第10页,按降价排序 我要做的是将1和2组件放在第三个组件中,这意味着1和2都是3的子组件,一旦子组件中的道具发生了变化(pageNumber和sort),将它们传递给父组件,并使用$watch执行函数,一旦检测到数据pageNumber和sort的变化,就请求API

我现在使用的是一个api旅行数据,我想用分页来显示它,同时用首选的排序方法来显示数据。我试图将所有内容分为三个部分:

  • 分页--用于页面的按钮
  • sortbar——用于对移动数据进行排序
  • 视图——根据上面的两个组件显示相应的数据。例如第10页,按降价排序
  • 我要做的是将1和2组件放在第三个组件中,这意味着1和2都是3的子组件,一旦子组件中的道具发生了变化(pageNumber和sort),将它们传递给父组件,并使用$watch执行函数,一旦检测到数据pageNumber和sort的变化,就请求API

    然而,我现在面临的问题是,我发现似乎我只能将两个子系统中的一个子系统的数据传递给父系统,如果一个子系统成功传递,那么另一个子系统失败,这取决于我将子系统放入父系统的顺序

    我只是想知道是否有可能同时将数据从两个子组件发送到一个父组件?谢谢您的帮助

    下面是我的代码:

  • 分页
  • 
    {{index+1}}
    导出默认值{
    名称:“分页”,
    道具:{
    页码:{
    类型:数字,
    }
    },
    方法:{
    重置页面(索引){
    this.pageNumber=索引+1;
    console.log(this.pageNumber)
    //使用“update:“props name””发出更新事件,并传递更改值。
    this.emit('update:pageNumber',this.pageNumber')//子元件與父元件雙向綁定
    },
    下一页(){
    this.pageNumber=this.pageNumber+1;
    this.emit('update:pageNumber',this.pageNumber');
    },
    上一页(){
    this.pageNumber=this.pageNumber-1;
    this.emit('update:pageNumber',this.pageNumber');
    },
    }
    };
    
  • 索特巴
  • 
    
    导出默认值{ 名称:“sortbar”, 道具:{ 排序:{ 类型:字符串, } }, 数据(){ 返回{ 价格排序:“低->高”, 分级排序:“” } }, 方法:{ 价格说明{ this.sort='price_desc'; this.pricesort='high->low' this.ratingsort=“” //使用“update:“props name””发出更新事件,并传递更改值。 this.emit('update:sort',this.sort'); }, 价格(asc){ this.sort='price_asc'; this.pricesort='high->low' this.ratingsort=“” this.emit('update:sort',this.sort'); }, 评级描述(){ this.sort='rating_desc'; this.ratingsort='high->low' this.pricesort='' this.emit('update:sort',this.sort'); }, 评级(asc){ this.sort='rating\u asc' this.ratingsort='low->high' this.pricesort='' this.emit('update:sort',this.sort'); }, } };
  • 看法
  • 
    {{pageNumber}}
    {{sort}}
    {{item.agency}{{item.rating | rating}}
    {{item.title}
    {{tag}}
    

    {{option.date | date}}({{option.date | day})

    可售{{option.quantity}}位

    {{item.tour\u days}

    {{item.min_price}currency}

    元起

    从“axios”导入axios; 从“/Pagination”导入分页 从“/Sortbar”导入Sortbar 导出默认值{ 名称:“groupdata”, 组成部分:{ 分页 }, 数据(){ 返回{ 孤岛加载:false, 数据:[], 排序:'price_desc', 页码:1 } }, //?
        <template>
            <div class="pagination">
                <div class="pagination-row">
                    <!-- previous page button -->
                    <button class="btn btn-light" @click = "previouspage"> &lt; </button>
                    <!-- pagination button --> 
                    <span v-for= "(item, index) in new Array(10)" :key="index">
                        <button class="btn btn-light"  @click = "resetpage(index)">{{ index+1 }}</button>
                    </span> 
                    <!-- next page button -->
                    <button class="btn btn-light" @click = "nextpage"> &gt; </button>
                </div>
            </div>
        </template>
          
        <script>
          export default {
            name: "pagination",
            props: {
                pageNumber:{ 
                    type: Number,
                }
            },
        
            methods: {
                resetpage(index) {
                    this.pageNumber = index + 1;
                    console.log(this.pageNumber)
                    //use 'update:"props-name"' to emit a update event, and pass the change value.
                    this.$emit('update:pageNumber', this.pageNumber); //子元件與父元件雙向綁定
                },
        
                nextpage() {
                    this.pageNumber = this.pageNumber + 1;
                    this.$emit('update:pageNumber', this.pageNumber);
                },
        
                previouspage() {
                    this.pageNumber = this.pageNumber - 1;
                    this.$emit('update:pageNumber', this.pageNumber);
                },
            }
          };
        </script>
    
        <template>
            <div class="sortbar">
                <nav class="navbar navbar-expand navbar-light bg-light" style="width:100%; margin: auto;"> 
                  <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav mr-auto">
                      <li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                          price:{{ pricesort }}
                        </a>
                        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                          <a class="dropdown-item btn" @click="price_desc" href="#">low->high</a>
                          <a class="dropdown-item btn" @click="price_asc" href="#">high->low</a>
                        </div>
                      </li>
                      <li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                          評分:{{ratingsort}}
                        </a>
                        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                          <a class="dropdown-item btn" @click="rating_desc" href="#">high->low</a>
                          <a class="dropdown-item btn" @click="rating_asc" href="#">low->high</a>
                        </div>
                      </li>
                    </ul>
                  </div>
                </nav> 
            </div>
        </template>
          
          <script>
          export default {
            name: "sortbar",
            props: {
              sort: {
                type: String,
              }
            },
            data() {
              return{
                pricesort: 'low->high',
                ratingsort: ''
              }
              },
            methods: {
              price_desc(){
                this.sort = 'price_desc';
                this.pricesort = 'high->low'
                this.ratingsort = ''
                //use 'update:"props-name"' to emit a update event, and pass the change value.
                this.$emit('update:sort', this.sort); 
              },
          
              price_asc(){
                this.sort = 'price_asc';
                this.pricesort = 'high->low'
                this.ratingsort = ''
                this.$emit('update:sort', this.sort);
              },
          
              rating_desc(){
                this.sort = 'rating_desc';
                this.ratingsort = 'high->low'
                this.pricesort = ''
                this.$emit('update:sort', this.sort);
              },
          
              rating_asc(){
                this.sort = 'rating_asc'
                this.ratingsort = 'low->high'
                this.pricesort = ''
                this.$emit('update:sort', this.sort);
              },
            }
          };
          </script>
    
        <template>
            <div class="groupdata">
              <!-- use `.sync` decorator to declare the counter is a two way binding props. -->
              <Sortbar :sort.sync="sort"></Sortbar>
              <Pagination :pageNumber.sync="pageNumber"></Pagination>
              {{ pageNumber }}
              {{ sort }}
              <div class="container">
                <div  v-for = "(item, index) in data" :key="index">
                  <div class = "cards">
                    <div class = 'img' style="width: 25%; height: 100%">
                      <img :src="item.image_url" style="width:100%; 
                      height:100%; 
                      object-fit:cover; ">
                    </div>
                    <div class='info' style="width: 75%; margin: auto;">
                      <h5 class = 'agency'>
                        {{ item.agency }} {{ item.rating | rating }}
                      </h5>
                      <h5 class = 'title'>
                        {{ item.title }}
                      </h5>
                      <div style="display: flex; padding-left: 20px;">
                        <div v-for = "(tag, index) in item.tags" :key="index">
                          <button class='tags'>{{ tag }}</button>
                        </div>
                      </div>
                      <hr style="margin: 5px 0px;">
                      <div class='timeandnum'>
                        <div style="width: 75%; display: flex; align-items: center;">
                          <div v-for = "(option, index) in item.group" :key="index" style="margin-right: 10px;">
                            <p class='date'>{{ option.date | date }} ( {{ option.date | day}} )</p>
                            <button class='num'> 可售{{ option.quantity }}位</button>
                          </div>
                        </div>
                        <div style="width: 25%;  margin-left: 20px;">
                          <p style="color:rgb(253, 163, 60); font-size: 1.8em; display: inline; font-weight: bold;">{{ item.tour_days }}</p>
                          <p style="font-size: 1em; display: inline;">天</p>
                          <p style="color:rgb(253, 163, 60); font-size: 1.8em; display: inline; font-weight: bold;">{{ item.min_price | currency }}</p>
                          <p style="font-size: 1em; display: inline;">元起</p>
                        </div>    
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div>
                <loading :active.sync="isloading"></loading>
              </div>
            </div>
          </template>
          
          <script>
          import axios from "axios";
          import Pagination from "./Pagination"
          import Sortbar from "./Sortbar"
          
          export default {
            name: "groupdata",
            components: {
              Pagination, Sortbar
            },
            data() {
              return {
                isloading: false,
                data: [],
                sort: 'price_desc',
                pageNumber: 1
              } 
            },
        
            //用watch監聽pageNumber這個data被更新的時候執行function
            watch: {
              pageNumber: function(){
                this.getdata(this.pageNumber,10, this.sort)
              },
              sort: function(){
                this.getdata(1,10, this.sort)
              }
            },
            created() {
              this.getdata(this.pageNumber,10, this.sort);
            },
          
            methods: {
              async getdata(page,rpp,sort) {
                try{
                this.data = [];
                this.isloading = true;
                let tourdata = await axios
                .get(`http://interview.tripresso.com/tour/search?page=${page}&row_per_page=${rpp}&sort=${sort}`)
                this.data = tourdata.data.data.tour_list;
              } catch (error) {
                console.log(error);
              } finally {
                setTimeout(() => {
                  this.isloading = false
                  },500)
              };  
              },
              updateSort(val) {
                this.sort = val;
              }
            }
          };
          </script>