vue/uni-app 父组件异步获取动态数据传递给子组件 获取不到值
问题:
vue 父组件异步请求获取数据,在请求数据没有返回数据时,子组件就已经加载了,并且它绑定的值也是空的
解决方法(两种):
方法一、
让子组件条件渲染,数据渲染完成后才渲染子组件
1 <!-- 父组件中 条件渲染子组件prizeRoll --> 2 <template> 3 <view> 4 <block v-if="flag"> 5 <prizeRoll :lists="rankList" :listNum="5"></prizeRoll> 6 </block> 7 <view> 8 </template> 9 10 <script> 11 import prizeRoll from '../../components/prize-info/prize-info.vue' 12 export default { 13 components: { prizeRoll }, 14 data() { 15 return { 16 rankList: [], 17 flag: flase, 18 } 19 }, 20 methods: { 21 // 异步请求数据 22 ranking() { 23 this.$api('gonggao.ranking').then((res) => { 24 this.rankList = res.data 25 // 数据渲染完成后,将flag值改为true 26 this.flag = true 27 }) 28 }, 29 }, 30 onLoad() { 31 this.ranking() 32 }, 33 } 34 </script>
方法二、
大概逻辑:使用vuex全局状态管理,其实简单,利用vuex的辅助函数(mapState,mapMutations)mapState是将state里面的数据映射到计算中(computed),mapMutations也是类似,把vuex中mutations的方法映射到组件里面,就可以在组件里面直接使用方法了,在vuex中使用异步(actions)去掉用接口,然后在接口成功的函数里面取触发同步(mutations)里面的方法,把得到数据传给mutations里面的方法里并且给state里面的属性赋值,然后就可以在子组件中使用computed计算中去获取数据并且渲染到页面上
vuex / index.js
1 <script> 2 import Vue from 'vue' 3 import Vuex from 'vuex' 4 import axios from 'axios' 5 Vue.use(Vuex) 6 export default new Vuex.Store({ 7 //定义初始数据 8 state: { 9 title: '', 10 list: [], 11 isShow: false 12 }, 13 //同步的方法 14 mutations: { 15 //向state 里面设置数据 16 changeListMutation(state, list) { 17 state.list = list 18 }, 19 //在list.vue里面点击下拉选项的时候触发 给state.title赋值 20 changeTitleMutation(state, title) { 21 state.title = title 22 }, 23 //selectinput.vue里面点击input的时候触发 给state.isShow赋值 24 toggleShow(state, isShow) { 25 state.isShow = isShow 26 } 27 }, 28 //异步的方法 29 actions: { 30 //在list.vue里面created生命周期里面触发 31 getListAction({ commit }) { 32 axios.get('/mock/5afd9dc0c088691e06a6ab45/example/dataList') 33 .then((res) => { 34 commit('changeListMutation', res.data) //调用mutations下面的changeListMutation方法并且传值过去 35 }) 36 .catch((error) => { 37 console.log(error) 38 }) 39 40 } 41 } 42 }) 43 // 触发异步里面的方法是用 this.$store.dispatch('这里是方法名') 44 // 触发同步里面的方法是用 this.$store.commit('这里是方法名') 45 </script>
父组件 select.vue
1 <template> 2 <div class="select"> 3 <div class="wrap"> 4 <selectInput></selectInput> 5 <list></list> 6 </div> 7 </div> 8 </template> 9 <script> 10 // 引入子组件 11 import selectInput from '@/components/selectInput' 12 import list from '@/components/list' 13 export default { 14 components:{ //加载子组件 15 selectInput, 16 list 17 }, 18 } 19 </script> 20 <style> 21 .select{ 22 background:#4a56fe; 23 width: 400px; 24 margin: 100px auto 0; 25 padding: 40px; 26 border-radius: 10px; 27 } 28 .wrap{ 29 background: #e3e5fe; 30 border-radius: 10px; 31 padding: 40px; 32 } 33 ul{ 34 list-style: none; 35 } 36 </style>
子组件 list.vue
该组件就是展示下拉选项,并且调用数据渲染
1 <template> 2 <div class="list"> 3 <ul> 4 <li v-for="(item,index) in list" :key="index" v-show="initShow" @click="changeTitle(item.title)">{{item.title}}</li> 5 </ul> 6 </div> 7 </template> 8 9 <script> 10 import {mapState,mapMutations} from 'vuex' // 将vuex中的state数据和mutations中的方法映射到组件中 11 export default { 12 //vue 生命周期(created)在实例创建之后,在数据初始化之前被调用 13 created(){ 14 this.$store.dispatch('getListAction') //调用vuex 中的 getListAction异步方法 15 }, 16 //计算state数据 17 computed:{ 18 ...mapState({ 19 list:'list', 20 initShow:'isShow' 21 }) 22 }, 23 methods:{ 24 changeTitle(title){ 25 this.$store.commit('changeTitleMutation',title) 26 this.$store.commit('toggleShow',!this.initShow) 27 } 28 } 29 } 30 </script> 31 // 触发异步里面的方法是用 this.$store.dispatch('这里是方法名') 32 // 触发同步里面的方法是用 this.$store.commit('这里是方法名') 33 34 <style> 35 .list{ 36 padding: 10px 0; 37 text-align: center; 38 } 39 li{ 40 line-height: 30px; 41 height: 30px; 42 border-radius: 15px; 43 cursor: pointer; 44 color:#535353; 45 } 46 li:hover{ 47 background: #ff705b; 48 color: #fff; 49 } 50 </style>
子组件 selectinput.vue
该组件展示选中的数据
1 <template> 2 <div class="inputBox"> 3 <input type="text" readonly :value="getTitle" @click="toggleShow" placeholder="你喜欢什么"> 4 </div> 5 </template> 6 7 <script> 8 export default { 9 computed:{ 10 // 获取vuex中的state数据并赋值绑定到 value上面 computed 里面的方法名其实就是相当于 data里面的数据,可以用this.getTitle 去访问 11 getTitle(){ 12 return this.$store.state.title 13 }, 14 // 初始化控制下拉选项显示隐藏的状态,如果isShow是false 则不限是下拉菜单,默认是false 15 initShow(){ 16 return this.$store.state.isShow 17 } 18 }, 19 methods:{ 20 //点击input的时候调用该方法,这个方法去触发mutations下面的toggleShow,去改变isShow的状态,默认是isShow等于false, 然后在点击的时候去改变isShow 等于true , !this.initShow就是true,如果是true的话,下拉选项才能出来,并将改变过后的值传给toggleShow方法,去给vuex/store.js 里面的state.isShow赋值。 21 toggleShow(){ 22 this.$store.commit('toggleShow',!this.initShow) 23 } 24 } 25 } 26 </script> 27 28 <style> 29 input{ 30 outline: none; 31 width: 100%; 32 height: 40px; 33 line-height: 40px; 34 border-radius: 10px; 35 border: 1px solid #d3d3d3; 36 text-indent: 20px; 37 color: #535353; 38 } 39 </style>