uni学习(10)搜索跳转页面

在这里插入图片描述
通过搜索框,或者其他跳转的搜索页面如上所示,

1、课程,文章问答的跳转框如下所示
在这里插入图片描述

<template>
	<view class="tab-bar">
		<view class="bar-view">
			<view class="bar-item " :class="{current:index==value}" v-for="(item, index) in tabs" :key="index" @click="changeTab(index)">{{item.name}}</view>

		</view>
	</view>
</template>

<script>
	export default {
		props: {
			tabs: {
				type: Array,
				default: () => [{
						id: 1,
						name: '课程'
					},
					{
						id: 2,
						name: '文章'
					},
					{
						id: 3,
						name: '问答'
					},
				]
			},
			value: { // vue 语法糖, v-model双向绑定:1. props声明value, 2. 修改它时触发input事件传递
				type: Number,
				default: 0
			}
		},
		data() {
			return {}
		},
		methods: {
			changeTab(index) {
				// 点击不同的标签才能改变值
				if(this.value!=index){
					// 2. 修改它时触发input事件传递数据
					this.$emit('input',index)
				}
			}
		}
	}
</script>

<style lang="scss">
	.tab-bar {
		width: 100%;
		height: 80rpx;
		background-color: #FFFFFF;
		border: 1px solid #efeff4;
		.bar-view {
			width: 100%;
			text-align: center;
			display: flex;
			.bar-item {
				flex: 1;
				font-size: 30rpx;
				line-height: 80rpx;
				position: relative;
				&:after {
					position: absolute;
					content: '';
					height: 0;
					width: 0;
					border-bottom: 6rpx solid $mxg-text-color-blue;
					border-radius: 20rpx;
					left: 50%;
					bottom: 6rpx;
					transform: translateX(-50%); //向x轴左边偏移百分之五十
					transition: 0.3s; //过渡的时长

				}
			}
			.current {
				color: $mxg-text-color-blue;

				&:after {
					width: 60rpx;
				}
			}

		}
	}
</style>

1、绑定点击的按钮样式

:class="{current:index==value}"

value在props中绑定

value: { // vue 语法糖, v-model双向绑定:1. props声明value, 2. 修改它时触发input事件传递
				type: Number,
				default: 0
}

点击触发changeTab方法,这个是与父组件双向绑定value值

changeTab(index) {
				// 点击不同的标签才能改变值
				if(this.value!=index){
					// 2. 修改它时触发input事件传递数据
					this.$emit('input',index)
				}
			}

父组件运用v-model双向绑定value,不能使用 :value 的方法,这种只能父组件向子组件传值,单向绑定

		<tab-bar  v-if="!searched" v-model="tabIndex"></tab-bar>

在data中绑定tabIndex

data() {
			return {
			
				tabIndex:0
			}
		},

2、综合排序,全部分类的编写
在这里插入图片描述

<template>
	<view class="down-bar row sticky-box">
		<!-- class="one"样式为flex=1表示平均分配 -->
		<!-- 禁止滚动 @touchmove.stop.prevent="()=>{} -->
		<view class="one" v-for="(item ,i) in downbarList" :key='i' @click="clickDownView(item)" @touchmove.stop.prevent="()=>{}">
			<view class=" center" :class="{active:item.active||(item.id||item.id===0)||item.categoryId}">
				<text>{{item.name}}</text>
				<text class="iconfont icon-down1" v-show="!item.active"></text>
				<text class="iconfont icon-Up" v-show="item.active"></text>

			</view>
			<view class="item-list" v-show="item.active">
				<category v-if="item.isCategory" :value='item' @searchByLabel="searchByLabel"></category>
				<view class="name" v-else :class="{active:info.name==item.name}" v-for="(info, index) in item.list" :key="index"
				 @click="changeInfo(item,info)">{{info.name}}</view>
			</view>
			<view class="cover" v-show="item.active"></view>

		</view>


	</view>
</template>

<script>
	import category from '@/pages/category/category.vue'
	export default {

		props: {
			param: {
				type: Object,
				default: null
			},
			downbar: {
				type: Array,
				default: () => [{
						type: 'sort',
						name: '综合排序',
						active: false, //是否被选中
						list: [{
								id: null,
								name: '综合排序'
							},
							{
								id: 'new',
								name: '最新排序'
							},
							{
								id: 'hot',
								name: '热门排序'
							}
						]
					},
					{
						type: 'label',
						name: '全部分类', // 放到最后一个元素
						active: false,
						isCategory: true // 分类
					}
				]
			}
		},


		data() {
			return {
				downbarList: []

			}
		},
		watch: {
			param: {
				handler(newValue) {
					console.log("请求参数", newValue)
					// 如果标签的名字不等于空,则下面进行
					if (newValue.name) {
						// 取downbarList最后一个元素
						let obj = this.downbar[this.downbar.length - 1]

						console.log(obj)
						//将全部分类替换成标签信息
						obj.name = newValue.name
						obj.id = newValue.labelId
						obj.activeIndex = newValue.activeIndex
						return
					}
				},
				immediate: true
			}
		},
		components: {
			category
		},

		// 因为小程序端不能直接更改props中父组件传过来的值,所以需要定义一个数据接收
		created() {
			this.downbarList = this.downbar

		},


		methods: {
			clickDownView(item) {
				console.log(item.name)
				//对downbar数组遍历,对每一个item进行比对,如果不同,active则为一律为false,不同则取反
				this.downbarList.forEach(
					(i) => {
						i.active = (item === i) ? !item.active : false
					}
				)
			},
			changeInfo(item, info) {
				if (item.name === info.name) return
				item.name = info.name
				item.id = info.id
				//向父组件发送查询数据
				this.$emit('search', {
					[item.type]: info.id
				})
			},
			//分类的子组件调用这个方法,来查询更新的类和方法
			searchByLabel(label) {
				console.log("传递过来的", label)
				this.$emit('search',{labelId:label.id,categoryId:label.categoryId})

			}
		}
	}
</script>

<style lang="scss">
	.down-bar {
		z-index: 100;
		background-color: #fff;
		font-size: 30rpx;
		line-height: 80rpx;

	}

	.item-list {
		z-index: 100;
		background-color: #FFFFFF;
		position: absolute;
		left: 0;
		right: 0;

		// border-radius: 20rpx;
		// width: 100%;
		// height: 300rpx;
		.name {
			padding-left: 80rpx;
			border-bottom: 1rpx solid #efeff4;
			margin-bottom: 5rpx;
		}

		.category {
			height: 580rpx;
		}

	}

	.active {
		color: $mxg-text-color-blue;
	}



	// 蒙层
	.cover {
		z-index: 99; //置于顶层
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		top: 160rpx;
		width: 100%;
		height: 100%;
		background-color: black;
		opacity: 0.2 !important; //透明度
	}

	// 粘顶的样式,页面滚动,顶部不动
	.sticky-box {
		position: -webkit-sticky;
		/* safari 浏览器 */
		position: sticky;
		/* 其他浏览器 */
		top: var(--window-top);

	}
</style>

clickDownView
点击触发的方法,并对父组件传递过来的参数遍历,
对downbar数组遍历,对每一个item进行比对,如果不同,active则为一律为false,不同则取反
item.active为true则为蓝色选中状态

clickDownView(item) {
				//对downbar数组遍历,对每一个item进行比对,如果不同,active则为一律为false,不同则取反
				this.downbarList.forEach(
					(i) => {
						i.active = (item === i) ? !item.active : false
					}
				)
	},

changeInfo方法
changeInfo左边点击时候触发的方法,将list中的子名称,赋值给他的父名称,这样就能点击展开页面后,显示出来

changeInfo(item, info) {
				if (item.name === info.name) return
				item.name = info.name
				item.id = info.id
				//向父组件发送查询数据
				this.$emit('search', {
					[item.type]: info.id
				})
			},
downbar: {
				type: Array,
				default: () => [{
						type: 'sort',
						name: '综合排序',
						active: false, //是否被选中
						list: [{
								id: null,
								name: '综合排序'
							},
							{
								id: 'new',
								name: '最新排序'
							},
							{
								id: 'hot',
								name: '热门排序'
							}
						]
					},
					{
						type: 'label',
						name: '全部分类', // 放到最后一个元素
						active: false,
						isCategory: true // 分类
					}
				]
			}

searchByLabel方法是接收子组件,category的中传参的方法

searchByLabel(label) {
				console.log("传递过来的", label)
				this.$emit('search',{labelId:label.id,categoryId:label.categoryId})
				}

在这里插入图片描述

子组件也就是分类页面,在这里插入图片描述

添加“不限”和全部分类的按钮

<template>
	<view class="category">
		<scroll-view scroll-y="true" class="left noScorll">
			<view class="title">
				<!--@click.stop阻止冒泡点击,不会影响父元素点击  -->
				<view v-for="(item, index) in categoryList" :class="{active:index==activeIndex}" :key="index" @click.stop="getLable(index,item)">{{item.name}}</view>

			</view>
		</scroll-view>
		<scroll-view scroll-y="true" class="right">
			<view class="tag">
				<!-- @click.stop阻止冒泡点击 -->
				<view v-for="(item,index) in labelList" :key="index" @click.stop="clicklabel(item)">{{item.name}}</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	import api from '@/api/course.js'
	export default {
		props: {
			//将搜索页当前的组件作为子组件,传递了对应的对象
			value: {
				type: Object,
				default: () => {}
			}
		},

		data() {
			return {
				categoryList: [], //左侧分类数据
				labelList: [], //右侧分类数据
				activeIndex: 0 //当前选中的下标


			}
		},
		mounted() {
			this.getList()
		},
		// 监听原生导航按钮
		onNavigationBarButtonTap(e) {
			console.log("-------")
			// uni.navigateTo({
			// 	url:'/pages/search/search'
			// })
			// this.navTo('/pages/search/search')
			if (e.index == 0) {
				this.navTo('/pages/search/search')
			}


		},

		methods: {
			async getList() {
				const res = await api.getCategoryList()
				this.categoryList = res.data
				console.log("查询分类的标签", res.data)

				//如果传递的数据不为空,则添加一个全部分类的按钮
				if (this.value) {
					//针对每一个分离下的标签列表,添加一个不限的按钮
					this.categoryList.forEach((item) => {
						// 添加不限按钮,并且把左边主列表的Id和name赋值给他 
						item.labelList.unshift({
							id: null,
							name: "不限",
							cname: item.name,
							categoryId: item.id
						})

					})
					this.activeIndex = this.value.activeIndex > -1 ? this.value.activeIndex + 1 : this.activeIndex
					this.categoryList.unshift({
						id: null,
						name: '全部分类'
					})
				}
				// 获取当前的标签列表
				this.getLable(this.activeIndex)

			},
			// 获取标签信息
			// index分类的下标,item当前分类的信息

			getLable(index, item) {

				// 选中的样式
				this.activeIndex = index;

				// 判断点击的是不是全部分类
				if (item && item.name === '全部分类') {
					// 如果有,则是分类弹窗,直接关闭窗口,将数据传递给下拉筛选的标题处
					this.searchPageChangeValue(item)
					return
				}


				//点击获取分类对象
				// 通过获取了分类对象,来获取标签列表
				const activeCategory = this.categoryList[index];
				// 通过分类对象获取标签列表
				this.labelList = activeCategory.labelList
				console.log(activeCategory.labelList)
			},
			// 点击标签跳转到搜索页面
			clicklabel(item) {
				// 如果有值就作为子组件 
				if (this.value) {
					// 将点击的标签信息回显到搜索页进行搜索
					this.searchPageChangeValue(item)
					return
				}
				const param = {
					labelId: item.id,
					name: item.name,
					activeIndex: this.activeIndex
				}
				this.navTo(`/pages/search/search?param=${JSON.stringify(param)}`)
			},
			// 弹框选择标签
			searchPageChangeValue(item) {
				// console.log(item)
				// 将上一次点击的名称和这次点击的对比,如果相同则不重复执行
				if (this.value.name !== item.name && this.value.name !== item.cname) {
					// 如果这条数据中有cname则是不限,没有则是普通的name
					this.value.name = item.cname || item.name
					// 标签ID
					this.value.id = item.id || null
					//分类ID点击的是不限则取分类ID
					this.value.categoryId = item.categoryId || null

					this.$emit("searchByLabel", this.value)
				}
				this.value.active = false

			}

		}
	}
</script>

<style lang="scss">
	page {
		height: 100%;
	}

	.category {
		display: flex;
		// flex-direction: row;

		height: 100%;

		.left {

			background-color: #F8F9FB;
			width: 260rpx;
			border-radius: 0 25rpx 25rpx 0;

			.title {
				view {
					// color: #005CC5;
					// width: 100%;
					// padding: 50rpx 20rpx;
					// text-align: center;

					// font-size: 30rpx;
					// position: relative;
					text-align: center;
					font-size: 30rpx;
					color: #888888;
					width: 100%;
					padding: 55rpx 30rpx;
					position: relative;

					&:before {
						position: absolute;
						content: '';
						width: 0;
						height: 0;
						border-right: 6rpx solid $mxg-color-primary;
						border-radius: 30rpx;
						left: 0;
						top: 50%;
						transform: translateY(-50%);
						transition: 0.3s;
					}
				}

				.active {
					color: $mxg-color-primary;
					font-size: 33rpx;
					font-weight: bold;

					&:before {
						height: 50rpx;
					}
				}


			}
		}

		.right {
			background-color: #FFFFFF;
			padding-left: 20rpx;
			margin: 0; //全屏铺满的效果

			.tag {
				display: flex; //指定flex布局
				flex-wrap: wrap; //自动换行
				padding-top: 35rpx;
				padding-left: 10rpx;

				view {
					font-size: 25rpx;
					line-height: 60rpx;
					border: 1px solid #999;
					border-radius: 30rpx;
					min-width: 160rpx;
					text-align: center;
					padding: 0 5rpx;
					margin: 15rpx 5rpx;
				}
			}
		}
	}
</style>

downBar页面引入的category 组件,绑定传入的数据,

		<category v-if="item.isCategory" :value='item' @searchByLabel="searchByLabel"></category>

在这里插入图片描述
父传子,向子函数传入参数,

:value='item'

category 中异步请求数据的方法,如果父组件传递了参数,则每行添加一个“不限”按钮,添加一个“全部分类”的总标签

async getList() {
				const res = await api.getCategoryList()
				this.categoryList = res.data
				console.log("查询分类的标签", res.data)

				//如果传递的数据不为空,则添加一个全部分类的按钮
				if (this.value) {
					//针对每一个分离下的标签列表,添加一个不限的按钮
					this.categoryList.forEach((item) => {
						// 添加不限按钮,并且把左边主列表的Id和name赋值给他 
						item.labelList.unshift({
							id: null,
							name: "不限",
							cname: item.name,
							categoryId: item.id
						})

					})
					this.activeIndex = this.value.activeIndex > -1 ? this.value.activeIndex + 1 :         this.activeIndex
					this.categoryList.unshift({
						id: null,
						name: '全部分类'
					})
				}
				// 获取当前的标签列表
				this.getLable(this.activeIndex)

			},

searchPageChangeValue这个方法是判断点击的对比,并赋值,然后传递给父组件, @searchByLabel=“searchByLabel”

// 弹框选择标签
			searchPageChangeValue(item) {
				// console.log(item)
				// 将上一次点击的名称和这次点击的对比,如果相同则不重复执行
				if (this.value.name !== item.name && this.value.name !== item.cname) {
					// 如果这条数据中有cname则是不限,没有则是普通的name
					this.value.name = item.cname || item.name
					// 标签ID
					this.value.id = item.id || null
					//分类ID点击的是不限则取分类ID
					this.value.categoryId = item.categoryId || null

					this.$emit("searchByLabel", this.value)
				}
				this.value.active = false

			}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值