父组件中vuex方法更新state子组件不能及时更新并渲染的完美解决方法

场景:

我实际用到的是这样的,我父组件引用子组件related,父组件调用获取页面详情的方法,更新了state值related,子组件根据该related来渲染相关新闻内容,但是页面打开的时候总是先加载子组件,子组件在渲染的时候还没有获取到更新之后的related值,即使在子组件中watch该值的变化依然不能渲染出来子组件的相关新闻内容。

我的解决办法:

父组件像子组件传值,当父组件执行了获取页面详情的方法之后,state值related更新,然后传给子组件,子组件再进行渲染,可以正常获取到。

父组件代码:

<template>
 <div id=\"newsDetails\">
  <mt-header title=\"详情\">
   <router-link to=\"/\" slot=\"left\">
    <mt-button icon=\"back\"></mt-button>
   </router-link>
  </mt-header>
  <div class=\"details clearfloat\">
   <h1 class=\"titleFont\">
    {{ title }}
   </h1>
   <div class=\"clearfloat sourceWrap\">
    <ul class=\"sourceFont\">
     <li v-if=\"(pubNews==true)\">
      <span class=\"source\">{{pubName}}</span>
     </li>
     <li>
      <span class=\"authorName\">{{authorName}}</span>
      <span class=\"time\">{{createAt|formatTime}}</span>
     </li>
    </ul>
    <span v-if=\"(pubNews==true)\" class=\'btnFollow\' @click=\"follow\">关注</span>
   </div>
   <div class=\"bodyFont clearfloat\" id=\"bodyFont\" ref=\"bodyFont\" :class=\"{bodyHeight:contentStatus}\">
    <div v-html=\"content\"></div>
    <div class=\"editor\" v-if=\"editorName\">责任编辑:{{editorName}}</div>
   </div>
   <div class=\"contentToggle\" @click=\"contentStatus=!contentStatus\" v-if=\"contentStatus\">阅读全文</div>
   <Related :related=\"related\"></Related>
    <!--重点是这里 父组件向子组件传值-->
 </div> </div> </template>

import { Toast } from \'mint-ui\';
 import {mapState} from \'vuex\'
 import Related from \'./Related.vue\'
 import moment from \'moment\';
 export default{
  name:\"NewsDetails\",
  components:{
   Related,
  },
  data(){
   return {
    id:this.$route.params.id,
    topicType:\"news\",
    contentStatus:false,
    curHeight:0,
    bodyHeight:5000,
    hotCommentScrollTop:0
   }
  },
  created(){
   this.id=this.$route.params.id;
   this.fetchData();
   moment.locale(\'zh-cn\');
  },
  mounted(){
   setTimeout(()=>{
    this.contentToggle();
   },500)
  },
  watch: {
   \'$route\'(to,from){
    this.id=this.$route.params.id;
    this.fetchData();
   }
  },
  computed: {
   ...mapState({
    title: state => state.newsDetails.title,
    authorName: state => state.newsDetails.authorName,
    pubNews: state => state.newsDetails.pubNews,
    pubName: state => state.newsDetails.pubName,
    editorName: state => state.newsDetails.editorName,
    createAt: state => state.newsDetails.createAt,
    content: state => state.newsDetails.content,
    myFavourite: state => state.newsDetails.myFavourite,
    related: state => state.newsDetails.related,
   })
  },
  filters:{
   formatTime(time){
    return moment(time).fromNow();
   },
  },
  methods:{
   fetchData(){
    this.$store.dispatch(\'getDetails\',this.id);
   },
   follow(){
    Toast(\'登录后进行关注\');
    this.$router.push(\"/login\");
   },
   contentToggle(){
    this.curHeight=this.$refs.bodyFont.offsetHeight;
    if(parseFloat(this.curHeight)>parseFloat(this.bodyHeight)){
     this.contentStatus=true;
    }else{
     this.contentStatus=false;
    }
//    this.hotCommentScrollTop=this.$refs.hotComment.height;
    console.log(this.hotCommentScrollTop);
   },
  }
 }

子组件related.vue

<template>
  <div v-if=\"lists.length>0\">
    <div class=\"tagTitle\"><span>相关新闻</span></div>
    <div class=\"listItem\" v-if=\"(item.type==\'little\')\" v-for=\"(item,index) in lists\" :to=\"{name:\'details\',params:{id:item.id}}\" :key=\"index\" @click=\"browserDetection()\">
     <div class=\"listImg1\">
      <!--<img :src=\"{lazy==loaded?item.thumb[0]:lazy==loading?\'../../assets/images/little_loading.png\':lazy==error?\'../../assets/images/little_loading.png\'}\" alt=\"\" v-lazy=\"item.thumb[0]\">-->
      <img :src=\"item.thumb[0]\" alt=\"\" v-lazy=\"item.thumb[0]\">
     </div>
     <div class=\'titleBox1\'>
      <p class=\"listTitle\">{{item.title}}</p>
      <div class=\"titleInfo\">
       <span class=\"openApp\">打开唐人家</span>
       <span v-if=\"item.top==true\" class=\"toTop\">置顶</span>
       <!--<svg class=\"icon\" aria-hidden=\"true\">
        <use xlink:href=\"#icon-dianzan\" rel=\"external nofollow\" ></use>
       </svg>-->
       <span class=\"like\">阅读 {{item.read}}</span>
       <span class=\"time\">{{item.createAt|formatTime}}</span>
      </div>
    </div>
   </div>
  </div>
</template>
<script>
 import {mapActions, mapState, mapGetters} from \'vuex\'
 import moment from \'moment\'
 export default{
  data(){
   return {
    lists: [],
    id:this.$route.params.id,
   }
  },
  props:{
    related:Array  //重点是这里
  },
  created(){
   moment.locale(\'zh-cn\');
  },
  /*computed: {
   ...mapState({
    related: state => state.newsDetails.related,
   })
  },*/
  filters:{
   formatTime(time){
    return moment(time).fromNow();
   },
  },
  methods:{
  },
  watch: {
   related (val) {
    this.lists = val;
   },
   \'$route\'(to,from){
    this.id=this.$route.params.id
   }
  }
 }
</script>

效果如图:

父组件中vuex方法更新state子组件不能及时更新并渲染的完美解决方法

以上所述是小编给大家介绍的父组件中vuex方法更新state子组件不能及时更新并渲染的完美解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容