美文网首页Vue.js专区Vue.js开发技巧前端Vue专辑
vue父组件异步获取动态数据传递给子组件 获取不到值的问题已完美

vue父组件异步获取动态数据传递给子组件 获取不到值的问题已完美

作者: WEB_克克 | 来源:发表于2018-07-18 15:01 被阅读237次
    前几天遇到一个问题,在父组件中使用axios获取异步数据传给子组件,但是发现子组件在渲染的时候并没有数据,在created里面打印也是空的,结果发现一开始子组件绑定的数据是空的,在请求数据没有返回数据时,子组件就已经加载了,并且他绑定的值也是空的,问题找到了,怎么解决那?有两种方法解决,请看下面代码。

    方法一、

    开始的时候让子组件隐藏,然后等数据返回的时候,让子组件显示。
    <template>
      <div class="list">
        <ul v-if="list.length != 0">
          <li v-for="(item,index) in list" :key="index"</li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      props:['getList'], //接收一个数组
        data(){
          return {
            list: []
          }
        },
        watch:{   // 使用监听的方式,监听数据的变化
          getList(val){
            this.list = val;
          }
        }
    }
    </script>
    
    不过这样方式不太合适,有bug,比如我点击一个按钮去获取数据,然后在弹框里面展示数据,弹框是一个子组件,在获取数据的这段过程有可能几百毫秒,也有可能十秒或者更长时间,难道我要在点击按钮过十秒才让弹框显示吗?这这这绝对不行,推荐使用方法二

    方法二、 推荐使用

    大概逻辑:使用vuex全局状态管理,其实简单,利用vuex的辅助函数(mapState,mapMutations)mapState是将state里面的数据映射到计算中(computed),mapMutations也是类似,把vuex中mutations的方法映射到组件里面,就可以在组件里面直接使用方法了,在vuex中使用异步(actions)去掉用接口,然后在接口成功的函数里面取触发同步(mutations)里面的方法,把得到数据传给mutations里面的方法里并且给state里面的属性赋值,然后就可以在子组件中使用computed计算中去获取数据并且渲染到页面上,其实说的有点绕( -_-"),但是看代码就明白了 。
    vuex / index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import axios from 'axios'
    Vue.use(Vuex) 
    export default new Vuex.Store({  
        //定义初始数据
        state: {  
            title: '',
            list: [],
            isShow: false
        },
        //同步的方法
        mutations: {
            //向state 里面设置数据
            changeListMutation(state, list) {
                state.list = list
            },
            //在list.vue里面点击下拉选项的时候触发 给state.title赋值
            changeTitleMutation(state, title) {
                state.title = title
            },
            //selectinput.vue里面点击input的时候触发 给state.isShow赋值
            toggleShow(state, isShow) {
                state.isShow = isShow 
            }
        },
        //异步的方法
        actions: {
            //在list.vue里面created生命周期里面触发
            getListAction({ commit }) {
                axios.get('/mock/5afd9dc0c088691e06a6ab45/example/dataList')
                    .then((res) => {
                        commit('changeListMutation', res.data) //调用mutations下面的changeListMutation方法并且传值过去
                    })
                    .catch((error) => {
                        console.log(error)
                    })
    
            }
        }
    })
    // 触发异步里面的方法是用 this.$store.dispatch('这里是方法名')
    // 触发同步里面的方法是用 this.$store.commit('这里是方法名')
    
    父组件 select.vue
    这个页面只是引入两个子组件,没有什么好说的
    <template>
      <div class="select">
        <div class="wrap">
            <selectInput></selectInput>
            <list></list>
        </div>
      </div>
    </template>
    <script>
      // 引入子组件 
      import selectInput from '@/components/selectInput'  
      import list from '@/components/list'
      export default {
        components:{   //加载子组件
          selectInput,
          list
        },
      }
    </script>
    <style>
      .select{
        background:#4a56fe;
        width: 400px;
        margin: 100px auto 0;
        padding: 40px;
        border-radius: 10px;
      }
      .wrap{
        background: #e3e5fe;
        border-radius: 10px;
        padding: 40px;
      }
      ul{
        list-style: none;
      }
    </style>
    
    子组件 list.vue
    该组件就是展示下拉选项,并且调用数据渲染
    import Vue from 'vue'
    import Vuex from 'vuex'
    import axios from 'axios'
    Vue.use(Vuex) 
    export default new Vuex.Store({  
        //定义初始数据
        state: {  
            title: '',
            list: [],
            isShow: false
        },
        //同步的方法
        mutations: {
            //向state 里面设置数据
            changeListMutation(state, list) {
                state.list = list
            },
            //在list.vue里面点击下拉选项的时候触发
            changeTitleMutation(state, title) {
                state.title = title
            },
            //selectinput.vue里面点击input的时候触发
            toggleShow(state, isShow) {
                state.isShow = isShow
            }
        },
        //异步的方法
        actions: {
            //在list.vue里面created生命周期里面触发
            getListAction({ commit }) {
                axios.get('/mock/5afd9dc0c088691e06a6ab45/example/dataList')
                .then((res) => {
                    commit('changeListMutation', res.data) //调用mutations下面的changeListMutation方法并且传值过去
                })
                .catch((error) => {
                    console.log(error)
                })
            }
        }
    })
    // 触发异步里面的方法是用 this.$store.dispatch('这里是方法名')
    // 触发同步里面的方法是用 this.$store.commit('这里是方法名')
    
    子组件 selectinput.vue
    该组件展示选中的数据
    <template>
      <div class="inputBox">
        <input type="text" readonly :value="getTitle" @click="toggleShow" placeholder="你喜欢什么">
      </div>
    </template>
    
    <script>
    export default {
      computed:{
        // 获取vuex中的state数据并赋值绑定到 value上面  computed 里面的方法名其实就是相当于 data里面的数据,可以用this.getTitle 去访问
        getTitle(){ 
          return this.$store.state.title
        },
        // 初始化控制下拉选项显示隐藏的状态,如果isShow是false 则不限是下拉菜单,默认是false
        initShow(){
            return this.$store.state.isShow
        }
      },
      methods:{
        //点击input的时候调用该方法,这个方法去触发mutations下面的toggleShow,去改变isShow的状态,默认是isShow等于false, 然后在点击的时候去改变isShow 等于true ,  !this.initShow就是true,如果是true的话,下拉选项才能出来,并将改变过后的值传给toggleShow方法,去给vuex/store.js 里面的state.isShow赋值。
        toggleShow(){
          this.$store.commit('toggleShow',!this.initShow)
        }
      }
    }
    </script>
    
    <style>
    input{
      outline: none;
      width: 100%;
      height: 40px;
      line-height: 40px;
      border-radius: 10px;
      border: 1px solid #d3d3d3;
      text-indent: 20px;
      color: #535353;
    }
    </style>
    
    
    image.png

    相关文章

      网友评论

        本文标题:vue父组件异步获取动态数据传递给子组件 获取不到值的问题已完美

        本文链接:https://www.haomeiwen.com/subject/mnhgpftx.html