前幾天遇到一個問題坚弱,在父組件中使用axios獲取異步數(shù)據(jù)傳給子組件,但是發(fā)現(xiàn)子組件在渲染的時候并沒有數(shù)據(jù)关摇,在created里面打印也是空的,結(jié)果發(fā)現(xiàn)一開始子組件綁定的數(shù)據(jù)是空的输虱,在請求數(shù)據(jù)沒有返回數(shù)據(jù)時,子組件就已經(jīng)加載了宪睹,并且他綁定的值也是空的愁茁,問題找到了亭病,怎么解決那鹅很?有兩種方法解決罪帖,請看下面代碼。
方法一胸蛛、
開始的時候讓子組件隱藏,然后等數(shù)據(jù)返回的時候污茵,讓子組件顯示葬项。
<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'], //接收一個數(shù)組
data(){
return {
list: []
}
},
watch:{ // 使用監(jiān)聽的方式,監(jiān)聽數(shù)據(jù)的變化
getList(val){
this.list = val;
}
}
}
</script>
不過這樣方式不太合適民珍,有bug襟士,比如我點擊一個按鈕去獲取數(shù)據(jù),然后在彈框里面展示數(shù)據(jù)陋桂,彈框是一個子組件逆趣,在獲取數(shù)據(jù)的這段過程有可能幾百毫秒嗜历,也有可能十秒或者更長時間,難道我要在點擊按鈕過十秒才讓彈框顯示嗎梨州?這這這絕對不行痕囱,推薦使用方法二
方法二暴匠、 推薦使用
大概邏輯:使用vuex全局狀態(tài)管理,其實簡單,利用vuex的輔助函數(shù)(mapState每窖,mapMutations)mapState是將state里面的數(shù)據(jù)映射到計算中(computed)帮掉,mapMutations也是類似窒典,把vuex中mutations的方法映射到組件里面旭寿,就可以在組件里面直接使用方法了,在vuex中使用異步(actions)去掉用接口崇败,然后在接口成功的函數(shù)里面取觸發(fā)同步(mutations)里面的方法,把得到數(shù)據(jù)傳給mutations里面的方法里并且給state里面的屬性賦值肩祥,然后就可以在子組件中使用computed計算中去獲取數(shù)據(jù)并且渲染到頁面上,其實說的有點繞( -_-")混狠,但是看代碼就明白了 岸霹。
vuex / index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
//定義初始數(shù)據(jù)
state: {
title: '',
list: [],
isShow: false
},
//同步的方法
mutations: {
//向state 里面設(shè)置數(shù)據(jù)
changeListMutation(state, list) {
state.list = list
},
//在list.vue里面點擊下拉選項的時候觸發(fā) 給state.title賦值
changeTitleMutation(state, title) {
state.title = title
},
//selectinput.vue里面點擊input的時候觸發(fā) 給state.isShow賦值
toggleShow(state, isShow) {
state.isShow = isShow
}
},
//異步的方法
actions: {
//在list.vue里面created生命周期里面觸發(fā)
getListAction({ commit }) {
axios.get('/mock/5afd9dc0c088691e06a6ab45/example/dataList')
.then((res) => {
commit('changeListMutation', res.data) //調(diào)用mutations下面的changeListMutation方法并且傳值過去
})
.catch((error) => {
console.log(error)
})
}
}
})
// 觸發(fā)異步里面的方法是用 this.$store.dispatch('這里是方法名')
// 觸發(fā)同步里面的方法是用 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
該組件就是展示下拉選項,并且調(diào)用數(shù)據(jù)渲染
<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數(shù)據(jù)和mutations中的方法映射到組件中
export default {
//vue 生命周期(created)在實例創(chuàng)建之后予弧,在數(shù)據(jù)初始化之前被調(diào)用
created(){
this.$store.dispatch('getListAction') //調(diào)用vuex 中的 getListAction異步方法
},
//計算state數(shù)據(jù)
computed:{
...mapState({
list:'list',
initShow:'isShow'
})
},
methods:{
changeTitle(title){
this.$store.commit('changeTitleMutation',title)
this.$store.commit('toggleShow',!this.initShow)
}
}
}
</script>
// 觸發(fā)異步里面的方法是用 this.$store.dispatch('這里是方法名')
// 觸發(fā)同步里面的方法是用 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
該組件展示選中的數(shù)據(jù)
<template>
<div class="inputBox">
<input type="text" readonly :value="getTitle" @click="toggleShow" placeholder="你喜歡什么">
</div>
</template>
<script>
export default {
computed:{
// 獲取vuex中的state數(shù)據(jù)并賦值綁定到 value上面 computed 里面的方法名其實就是相當于 data里面的數(shù)據(jù),可以用this.getTitle 去訪問
getTitle(){
return this.$store.state.title
},
// 初始化控制下拉選項顯示隱藏的狀態(tài)掖蛤,如果isShow是false 則不限是下拉菜單,默認是false
initShow(){
return this.$store.state.isShow
}
},
methods:{
//點擊input的時候調(diào)用該方法蚓庭,這個方法去觸發(fā)mutations下面的toggleShow致讥,去改變isShow的狀態(tài),默認是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>