子组件
子组件通过props接受父组件传来的值,通过this.$emit(‘方法名’, this.result)
这里通过父组件来控制子组件的弹出层显示:
props: {
popShow: {
type: Boolean,
default: false
}
},
注意,这里的popShow和data中的数据不可重名,并且可以用this来引用,如在组件内部我通过locationPopShow来控制弹出层隐藏和显示,在组件的mounted周期中我们可以拿到父组件传来的值
mounted() {
this.inItData()
console.log('子组件传值', this.popShow)
this.locationPopShow = this.popShow
},
但是mounted生命周期在组件的创建到销毁只会被调用一次,如果我们这个参数是变量,显然只用mounted中拿到的值显然不行,这时可以使用watch方法来帮我们实现,如控制弹出层的显示隐藏
watch: {
popShow(newVal, oldVal) {
console.log(newVal, oldVal)
this.locationPopShow = newVal
}
},
向父组件传参
this.$emit('areaResult', this.result)
完整代码
<template>
<view>
<view class="" @click="locationPopShow=true">
子组件打开定位
</view>
<u-popup mode="top" v-model="locationPopShow">
<view class="u-flex" style="justify-content:center;font-size:32rpx;font-weight:500">
<view class="first-colum" :class="level>0?'border-r':''" style="margin:30rpx;line-height:50rpx;flex:1">
<scroll-view scroll-y="true" style='height:400rpx'>
<view class="" :style="{color:item.status?'#55aaff':'#333'}" @click='chooseChildren(arealist,item,1)' v-for="(item,index) in arealist"
:key='index'>
{{item.label}}
</view>
</scroll-view>
</view>
<view class="second-colum" v-if='level>0' :class="level>1?'border-r':''" style="margin:30rpx;line-height:50rpx;flex:1">
<scroll-view scroll-y="true" style='height:400rpx'>
<view class="" :style="{color:item1.status?'#55aaff':'#333'}" @click='chooseChildren(firstChildren,item1,2)'
v-for="(item1,index1) in firstChildren" :key='index1'>
{{item1.label}}
</view>
</scroll-view>
</view>
<view class="third-colum" v-if='level>1' style="margin:30rpx;line-height:50rpx;flex:1">
<scroll-view scroll-y="true" style='height:400rpx'>
<view class="" :style="{color:item2.status?'#55aaff':'#333'}" @click='chooseChildren(secondChildren,item2,3)'
v-for="(item2,index2) in secondChildren" :key='index2'>
{{item2.label}}
</view>
</scroll-view>
</view>
</view>
<view class="u-flex" style='justify-content:space-around;padding-bottom: 30rpx;'>
<u-button type='primary' @click='popReset' :custom-style="{backgroundColor:'#cccccc',width:'150rpx'}">重置</u-button>
<u-button type='primary' @click="popConfirm" :custom-style="{backgroundColor:'#55aaff',width:'150rpx'}">确定</u-button>
</view>
</u-popup>
</view>
</template>
<script>
import areaData from '../../common/areaData.js'
export default {
props: {
popShow: {
type: Boolean,
default: false
}
},
data() {
return {
level: 0,
result: [],
firstChildren: [],
secondChildren: [],
thirdChildren: [],
locationPopShow: false,
arealist: areaData,
list: []
}
},
onLoad() {
this.inItData()
},
mounted() {
this.inItData()
console.log('子组件传值', this.popShow)
this.locationPopShow = this.popShow
},
watch: {
popShow(newVal, oldVal) {
console.log(newVal, oldVal)
this.locationPopShow = newVal
}
},
computed: {
getArray(arr, value, label) {
let array = []
array = arr.filter((val, idx) => {
return val.code == value
})
console.log('筛选结果', array)
return array.children
},
},
methods: {
inItData() {
this.arealist.map((value, index) => {
value.status = false
if (value.children) {
let obj = {
status: true,
code: value.code,
label: '不限',
name: value.label
}
if (value.children[0].label != '不限') value.children.unshift(obj)
if (value.children.length > 0) {
let arr2 = value.children
arr2.map((value2, index2) => {
// console.log(value2)
if (value2.children) {
let obj2 = {
status: true,
code: value2.code,
label: '不限',
name: value2.label
}
if (value2.children[0].label != '不限') value2.children.unshift(obj2)
}
})
}
}
})
console.log(this.arealist)
},
popReset() {
this.arealist.map((value, index) => {
value.status = false
this.firstChildren = []
this.secondChildren = []
this.thirdChildren = []
})
// this.locationPopShow=false
console.log(this.arealist)
this.level = 0
},
popConfirm() {
// console.log('thirdChildren提交结果',this.result)
this.result = this.arealist.filter(value => value.status == true)
if (this.result.length == 0) {
this.$emit('areaResult', this.result)
return
}
if (this.result[0].children) {
this.result = this.result[0].children.filter(value => value.status == true)
if (this.result[0].children) {
this.result = this.result[0].children.filter(value => value.status == true)
}
}
if (this.result.length > 1) {
let codes = ''
this.result.map(value => {
if (codes == '') {
codes += value.code
} else {
codes += ',' + value.code
}
})
this.result = [{
label: '多选',
code: codes
}]
}
// console.log('arealist提交结果3',this.result)
// 子组件向父组件传参
this.$emit('areaResult', this.result)
},
statusInit(arr) {
arr.map((value, index) => {
if (value.label != '不限') {
value.status = false
// console.log(value)
} else {
value.status = true
}
})
this.$forceUpdate()
},
arrayChildren(arr, value, label) {
let array = []
array = arr.filter((val, idx) => {
return val.code == value
})
return array
},
chooseChildren(arr, item, idx) {
console.log(idx)
if (item.label == '不限') {
item.status = !item.status
this.level = idx - 1
if (idx == 2) {
this.statusInit(this.firstChildren)
} else if (idx == 3) {
this.statusInit(this.secondChildren)
}
this.$forceUpdate()
return
}
if (idx == 1) {
this.statusInit(this.arealist)
this.firstChildren = this.arrayChildren(arr, item.code)[0].children
// console.log('secondChildren',this.secondChildren)
} else if (idx == 2) {
this.statusInit(this.firstChildren)
this.secondChildren = this.arrayChildren(arr, item.code)[0].children
this.firstChildren[0].status = false
} else if (idx == 3) {
this.secondChildren[0].status = false
// console.log('筛选结果',item)
}
item.status = !item.status
this.$forceUpdate()
this.level = idx
}
}
}
</script>
<style scoped>
.border-r {
border-right: 2rpx solid #ededed;
}
</style>
父组件
父组件通过绑定事件来监听子组件传过来的值,通过props传递参数,需要注意:监听函数的名字要和子组件保持一直,props参数也要保持一致
<template>
<view>
<view class="" @click="popTest">
父组件打开
</view>
<location-select :popShow='popShow' @areaResult='areaResult'></location-select>
</view>
</template>
<script>
import locationSelect from '@/pages/locationSelect/locationSelect.vue'
export default {
data() {
return {
list:[],
popShow:false
}
},
components:{
locationSelect
},
methods: {
popTest(){
this.popShow=true
console.log('父组件传值')
},
areaResult(e){
console.log('子组件传值',e)
}
}
}
</script>
<style>
</style>
兄弟组件传值
兄弟组件间的传值可以建立一个事件中心,eventBus。首先需要创建一个事件总线并将其导出, 以便其他模块可以使用或者监听它bus.js:
import Vue from 'vue'
export const bus = new Vue()
使用时先引入bus
import {bus} from '@/bus.js'
触发事件的组件
methods:{
additionHandle(){
bus.$emit('事件名', {
属性:值
})
}
}
接受事件的组件在mounted中监听
mounted() {
//事件名要保持一致
bus.$on('事件名', arg=> {
console.log('组件传值',arg)
})
}
示例中用到了uview的组件,基于uview才能正常运行。
测试数据可自定义
const areaData = [
{
'label': '江苏省',
'code': '32',
'children': [
{
'label': '南京市',
'code': '3201',
'children': [{
'label': '南京市',
'code': '320100'
},
{
'label': '玄武区',
'code': '320102'
},
{
'label': '秦淮区',
'code': '320104'
},
{
'label': '建邺区',
'code': '320105'
},
{
'label': '鼓楼区',
'code': '320106'
},
{
'label': '浦口区',
'code': '320111'
},
{
'label': '栖霞区',
'code': '320113'
},
{
'label': '雨花台区',
'code': '320114'
},
{
'label': '江宁区',
'code': '320115'
},
{
'label': '六合区',
'code': '320116'
},
{
'label': '溧水区',
'code': '320117'
},
{
'label': '高淳区',
'code': '320118'
}
]
},
]}
]