vue父组件异步获取动态数据传递给子组件获取不到值

原理:

       在父组件中使用axios获取异步数据传给子组件,但是发现子组件在渲染的时候并没有数据,在created里面打印也是空的,结果发现一开始子组件绑定的数据是空的,在请求数据没有返回数据时,子组件就已经加载了,并且他绑定的值也是空的

使用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)
                })

        }
    }
})

父组件 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;
     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
<template>
  <div class="list">
    <ul>
      <li v-for="(item,index) in list" :key="index" v-show="initShow" @click="changeTitle(item.title)">{{item.title}}</li>
    </ul>
  </div>
</template>

<script>
    import {mapState,mapMutations} from 'vuex'  // 将vuex中的state数据和mutations中的方法映射到组件中
    export default {
        //vue 生命周期(created)在实例创建之后,在数据初始化之前被调用
        created(){  
            this.$store.dispatch('getListAction')  //调用vuex 中的 getListAction异步方法
        },
        //计算state数据
        computed:{
            ...mapState({
              list:'list',
              initShow:'isShow'
            })
        },
        methods:{
            changeTitle(title){
              this.$store.commit('changeTitleMutation',title)
              this.$store.commit('toggleShow',!this.initShow)
            }
        }
    }
</script>
// 触发异步里面的方法是用 this.$store.dispatch('这里是方法名')
// 触发同步里面的方法是用 this.$store.commit('这里是方法名')

<style>
  .list{
    padding: 10px 0;
    text-align: center;
  }
  li{
    line-height: 30px;
    height: 30px;
    border-radius: 15px;
    cursor: pointer;
    color:#535353;
  }
  li:hover{
    background: #ff705b;
    color: #fff;
  }
</style>


子组件 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;
   100%;
  height: 40px;
  line-height: 40px;
  border-radius: 10px;
  border: 1px solid #d3d3d3;
  text-indent: 20px;
  color: #535353;
}
</style>















原文地址:https://www.cnblogs.com/zhouyideboke/p/11193600.html