在基于nuxt的移动端页面中引用mint UI的popup组件之父子组件传值

  最近在做移动端的wap页面,考虑到要做SEO,所以选定了nuxt+vue+mint ui。

  有一个需求是这样的,点击头部菜单栏,出现一个气泡,点击返回首页。

  

由于一些页面没有统一引用mint的mt-header组件,所以决定把这个气泡(popup)封装为一个组件,在需要的地方调用。点击header右侧的三个点时,控制popup的显示和隐藏,因此涉及到了父子组件传值。代码如下:
 1 <template>
 2     <div>
 3        <mt-header :title="title">
 4             <a @click="$router.go(-1)" slot="left">
 5                 <mt-button icon="back" v-if="headerType == 'back'">返回</mt-button>
 6                 <mt-button @click="handleClose" v-if="headerType == 'close'">关闭</mt-button>
 7             </a>
 8             <mt-button icon="more" slot="right" v-if="headerType == 'more'"  @click="TogglePopupMore"></mt-button>
 9             <mt-button  slot="right" v-if="headerType == 'mRight'">{{stringRight}}</mt-button>
10             <mt-button slot="right" v-if="headerType == 'setting'">
11                 <div>
12                     <i class="icon iconfont icon-31shezhi"></i>
13                 </div>
14             </mt-button>
15         </mt-header>
16         <v-indexPopup v-model="tab"></v-indexPopup>
17     </div>
18 </template>

 第8行TogglePopupMore这个方法会切换popupMoreTrigger的true和false,进而控制popup的显示和隐藏,第16行就是引入的气泡这个组件。组件代码如下:

<template>
  <div class="main">
    <mt-popup
      class="show-more-popup"
      v-model="popupMoreTrigger"
      popup-transition="popup-fade">
      <div class="show-more-popup-item">
        <nuxt-link to="/">首页</nuxt-link>
      </div>
    </mt-popup>
  </div>
</template>

关于popup的官方文档截图如下:

划重点:popupVisible是通过v-model绑定的,这个神操作直接导致了后面的一系列事故,当然也促成了这篇博客的诞生...插一句,新版API已经不再使用这种方式了,而是通过:visible.sync="popupVisible"绑定,也许作者大大也意识到这么做的不妥了吧。新版中文文档地址:http://mint-ui.github.io/docs/#/zh-cn2。于是乎问题如约而至:

这里在beforeMount这个钩子函数中分别打印了popupMoreTrigger和popupMoreTrigger2,但是发现这两个值并不像等。我又监听popupMoreTrigger的值,发现点击菜单栏的右侧按钮时,popupMoreTrigger的值已经改变了,并且也正确地传到了子组件中,只是popupMoreTrigger2没有跟着一起变,所以气泡不能显示出来。既然在data中重新声明不可以,我就放在计算属性中在试试呗~

 然而...报错提示:Property or method "showPopup" is not defined on the instance but referenced during render.直接在props中使用也是不可以的,这是由vue自身的单向数据流产生的:(防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解)

报错内容为:Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "popupMoreTrigger"。

  导致这些问题的根源就在于popup的显隐性字段是通过v-model绑定的,这本身是双向绑定的,而vue.js的机制又不允许这么做。用啥不好非用个v-model,看在新版api已经改了的份上,我就原谅你吧。后来朋友说可以尝试使用对象来传值,这个可以用双向绑定。一通修改之后代码如下:

父组件data部分:

data () {
        return {
            tab:{
                popupMoreTrigger: false,
            }
        };
    },

父组件methods部分:

methods: {
        TogglePopupMore(){
            this.tab.popupMoreTrigger = !this.tab.popupMoreTrigger;
        },
    }

父组件调用子组件部分:(此时传过去的tab是一个对象哦)

<v-indexPopup v-model="tab"></v-indexPopup>

子组件代码如下:

<template>
  <div class="main">
    <mt-popup
      class="show-more-popup"
      v-model="value.popupMoreTrigger"
      popup-transition="popup-fade">
      <div class="show-more-popup-item">
        <nuxt-link to="/">首页</nuxt-link>
      </div>
    </mt-popup>
  </div>
</template>

<script type='text/ecmascript-6'>
  import { Loadmore } from 'mint-ui';

  export default {
    data () {
      return {

      };
    },
    props: {
      value: {
        type: Object,
        default: {}
      }
      
    },
  }
</script>
<style scoped>
  .show-more-popup{
    width: auto;
    border-radius: 6px;
    padding: 5px 15px;
    top: 50px;
    bottom: auto;
    right: 0;
    left: auto;
    text-align: center;
    -webkit-transform: none;
    transform: none;
  }
  .show-more-popup:before{
    display: inline-block;
    width: 0;
    height: 0;
    border: solid transparent;
    border-width: 10px;
    border-bottom-color: #fff;
    content: "";
    position: absolute;
    top: -20px;
    right: 10px;
  }
  .show-more-popup-item{
    color: #333;
  }
</style>

主要区别就是把布尔值的popupMoreTrigger改成了对象。

  四五月份的大事是跳槽换了工作,这是一个新的开始。

  六七月份的大事是开始维护博客,这是一个好的开始。anyway,加油干吧。

posted @ 2018-07-12 16:39  心砚  阅读(2910)  评论(1编辑  收藏  举报