在基于nuxt的移动端页面中引用mint UI的popup组件之父子组件传值
最近在做移动端的wap页面,考虑到要做SEO,所以选定了nuxt+vue+mint ui。
有一个需求是这样的,点击头部菜单栏,出现一个气泡,点击返回首页。
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,加油干吧。