# uni-ui宫格布局+proxy代理+弹出层
 http://www.codeboy.com:9999/data/product/list.php
功能点:
请求接口加载数据列表形式展示
触底加载 翻页 发送请求翻页数据 传参页数
- 提示文字 
加载中...ui-load组件 status控制显示的文字 - 触底事件 发送请求 拼接数据
 
- 提示文字 
 下拉刷新 更新最新数据 请求第一页数据
页面下拉刷新需要开启
pages.json
pages.json开启下拉操作
下拉事件
onPullDownRefresh发送请求 加载第一页
回到顶部 当数据列表较长 从底部快速回到顶部方式
- 当页面滚动到一定位置的时候,再出现回到顶部的按钮
 - 点击按钮,滚动到页面的初始位置 顶部位置
 
<template>
	<view v-if="data">
		<uni-list>
			<uni-list-item v-for="(item,index) in data.data" :key="index" :clickable="true" :showArrow="true">
				<!--使用插槽的方式写入内容 否则不能够显示 -->
				<template slot="body">
					<view class="item">
						<image :src="`http://www.codeboy.com:9999/${item.pic}`" mode=""></image>
						<view>
							<view>{{item.title}}</view>
							<view>¥{{item.price}}</view>
						</view>
					</view>
				</template>
			</uni-list-item>
		</uni-list>
		<!-- 加载更多组件 -->
		<!-- status属性只有三个  more loading noMore 是固定只能传这三个值-->
		<uni-load-more :status="status"></uni-load-more>
		<!-- 回到顶部按钮 -->
		<!-- @ vue中的事件绑定 -->
		<view class="btn-gotop" v-show="showBtn" @click="goTop">
			<uni-icons type="arrow-up"></uni-icons>
		</view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				data: null,
				// 加载更多组件 状态管理
				status:'more',
				showBtn:false
			}
		},
		// 下拉事件
		onPullDownRefresh() {
			// console.log('下拉事件触发了')
			// 下拉刷新 就是加载第一页数据
			this.getData(1)
			// 停止下拉刷新的状态
			
		},
		// 监听滚动位置
		onPageScroll(e) {
			console.log(e.scrollTop)
			// 当滚动距离顶部>1500 设置回到顶部按钮显示状态为true
			// if(e.scrollTop>1500){
			// 	this.showBtn = true
			// }else{
			// 	this.showBtn = false
			// }
			// 比较运算符的返回值就是bool类型 刚好前面bool值
			this.showBtn = e.scrollTop >1500
		},
		// 触底事件
		onReachBottom() {
			// console.log('到底了');
			// 加载翻页数据
			// 获取当前页数  获取当前是第几页  总页数
			// es6 解构语法
			const {pno,pageCount} =this.data
			// console.log(pno)
			// 判断当前页数是最大页数, 说明后续没有数据了 不进行后续操作
			if(pno == pageCount){
				// 加载更多的组件的状态修改为 noMore
				this.status = 'noMore'
				// return 后续代码都不执行
				return;
			}
			// 请求接口 翻页
			// 请求数据时,把加载更多组件的状态修改为加载中
			this.status = "loading"
			this.getData(pno+1)
		},
		// 发请求 拿数据  存本地  做展示
		// onLoad或者mounted中发送请求
		mounted() {
			this.getData()
		},
		methods:{
			// 回到顶部处理
			goTop(){
				uni.pageScrollTo({
					// 0 回到顶部
					scrollTop:0,
					duration:100
				})
			},
			// 请求数据
			// 默认第一页
			getData(pno = 1){
				const url = 'http://www.codeboy.com:9999/data/product/list.php'
				uni.request({
					url,
					method: 'GET',
					// {pno:pno}
					data: {pno},
					success: res => {
						console.log(res);
						// 确认请求数据成功后 停止下拉
						uni.stopPullDownRefresh()
						// 拼接数据  旧数据+新数据
						// 非第一页拼接
						if(pno>1){
							// es6 []数组合并 ...展开
							// 拼接数据 旧数据+新数据
							res.data.data = [...this.data.data,...res.data.data]
						}
						this.data = res.data
					},
					fail: () => {},
					complete: () => {}
				});
			}
		}
	}
</script>
<!-- scss 安装scss插件 -->
<style scoped lang="scss">
	.item{
		// 布局方式 弹性盒子
		display: flex;
		image{
			width: 180rpx;
			height:180rpx;
			// 方式1设置最小宽度
			// min-width: 180rpx;
			// 方法2:flex none 不压缩 不收缩
			flex: none;
		}
		>view{
			display: flex;
			flex-direction: column;
			// 主轴对其方式 
			justify-content: space-between;
			// frist-of-type
			>view:first-of-type{
				// 两行折行 不显示  ...代替
				text-overflow: -o-ellipsis-lastline;
				  overflow: hidden;
				  text-overflow: ellipsis;
				  display: -webkit-box;
				  -webkit-line-clamp: 2;
				  line-clamp: 2;
				  -webkit-box-orient: vertical;
			}
			>view:last-of-type{
				font-size: 1.1em;
				font-weight: bold;
				color: #ff0000;
			}
		}
	}
	.btn-gotop{
		width:100rpx;
		height:100rpx;
		background-color: rgba(0,0,0,0.3);
		position: fixed;
		right:30rpx;
		bottom: 100rpx;
		display: flex;
		justify-content: center;
		border-radius: 50%;
		align-items:center ;
	}
</style>
# 宫格布局
常用来实现多个数据的布局
<template>
	<view>
		<!-- ugrid 宫格 -->
		<!-- hightlight 点击高亮 showBorder显示边框  square 方形 -->
		<uni-grid :column="2" :highlight="false" :showBorder="false" :square="false">
			<uni-grid-item v-for="(item,index) in skills" :key="index">
				{{item}}
			</uni-grid-item>
		</uni-grid>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				skills: ['html','css','javascript','Jquery','vue','react','angular']
			}
		},
		
	}
</script>
<style scoped>
</style>
# 案例:斗鱼直播房间列表 双列布局
实现思路:
发送请求 接收回数据
https://m.douyu.com/api/room/list?page=1&type=yz
对于数据进行存储,并展示到页面中

客户端浏览器由于
同源策略的影响,会出现跨域问题。 同源策略它是浏览器的基本安全策略,目的是保障用户信息的安全。 不同域之间不能够相互请求和操作对应的数据(cookie) 协议不同 http https http://www.a.com https://www.a.com 域名不同;http://www.a.com http://bbb.a.com 端口的不同: http://www.a.com:3000 http://www.a.com:8080
解决跨域问题:常见的方式:
jsonp需要服务端配置返回数据src或scriptsrc非官方的 存在安全注入风险 不流行cors中间件服务端直接配置允许跨域 服务端人员配置 实际业务运营
proxy代理 启动一个代理服务 请求数据返回 底层是http-middeware-proxy插件 基于NodeJS 开发过程中 业务运营
uni-app基于vue开发的,之前学习的vue proxy代理方式 在这里也同样使用
HBX内置浏览器自带解决跨域问题   跨域问题由浏览器限制
建立配置文件
vue.config.js
//  vue.config.js  项目包根目录下  
// es6的导出模块 模块暴露  外面才可以调用
module.exports={
	// 配置开发服务器
	devServer:{
		// 代理
		proxy:{
			// https://m.douyu.com/api/room/list?type=yz
			// 配合proxy 请求地址需要进行修改
			// /douyu/api/room/list?type=yz 代理修改地址
			// https://m.douyu.com/douyu/api/room/list?type=yz
			// 代理段
			// 标识头
			"/douyu":{
				// 代理到的远程地址
				target:'https://m.douyu.com',
				// 域名变化的 不一致的 大部分情况都是不一样的
				changeOrigin:true,
				// 根据协议配置secure https 要配置为true
				secure:true,
				// 路径重写
				pathRewrite:{
					// ^ 正则 以xx开头
					"^/douyu":""
				}
			}
		}
	}
}
2.接口地址也需要修改
getDate(page = 1) {
				// proxy代理需要告知哪个接口地址需要代理 
				// 加一个表示信息 /douyu
				const url = '/douyu/api/room/list?type=yz'
				uni.request({
					url,
					method: 'GET',
					// {page:page}缩写 {page}
					data: {page},
					success: res => {
						console.log(res);
					},
					fail: () => {},
					complete: () => {}
				});
			}
3.重启项目包 让配置文件生效
全部的代码如下
<template>
	<view v-if="data">
		<!-- ugrid -->
		<!-- square 正方形 -->
		<uni-grid :column="2" :square="false" :highlight="false" :showBorder="false">
			<uni-grid-item v-for="(item,index) in data.list" :key="index">
				<view class="item">
					<view>
						<image :src="item.roomSrc"></image>
						<view><uni-icons type="person" color="white"></uni-icons>{{item.nickname}}</view>
						<view><uni-icons type="fire" color="white"></uni-icons>{{item.hn}}</view>
					</view>
					<view>{{item.roomName}}</view>
				</view>
			</uni-grid-item>
		</uni-grid>
		<uni-load-more :status="status"></uni-load-more>
		<button type="default" class="goTopBtn" @click="goTop" v-show="goTopBtn">
			<uni-icons type="arrow-up" color="white" :size="30"></uni-icons>
		</button>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				data: null,
				status:"more",
				goTopBtn:false
			}
		},
		//监听页面滚动  页面滚动生命周期函数
		onPageScroll(e){
			console.log(e.scrollTop)
			this.goTopBtn = e.scrollTop>1000
		},
		// 触底加载
		onReachBottom() {
			console.log("到底部了")
			const {nowPage,pageCount} = this.data
			if(nowPage == pageCount){
				this.status = 'noMore'
				return
			}
			this.status = 'loading'
			this.getDate(nowPage+1)
		},
		// 下拉刷新
		onPullDownRefresh() {
			console.log("下拉了")
			this.getDate(1)
		},
		// 发请求 拿数据  存本地  做展示
		mounted() {
			this.getDate()
		},
		methods: {
			// 回到顶部
			goTop(){
					uni.pageScrollTo({
						scrollTop:0,
						duration:500
					})
			},
			getDate(page = 1) {
				// proxy代理需要告知哪个接口地址需要代理 
				// 加一个表示信息 /douyu
				const url = '/douyu/api/room/list?type=yz'
				uni.request({
					url,
					method: 'GET',
					// {page:page}缩写 {page}
					data: {page},
					success: res => {
						console.log(res);
						uni.stopPullDownRefresh()
						if(page>1){
							res.data.data.list = [...this.data.list,...res.data.data.list]
						}
						this.data = res.data.data
					},
					fail: () => {},
					complete: () => {}
				});
			}
		},
	}
</script>
<style scoped lang="scss">
	.goTopBtn{
		position: fixed;
		right: 10rpx;
		bottom: 10rpx;
		width: 100rpx;
		height: 100rpx;
		border-radius: 50%;
		background-color: rgba(0,0,0,0.3);
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.item{
		padding: 10rpx;
		image{
			width: 100%;
			height: 250rpx;
			border-radius: 4px;
			display: block;
		}
		>view:first-of-type{
			position: relative;
			view:first-of-type{
				position: absolute;
				left: 0;
				bottom: 0;
				color: white;
				font-size: 0.9em;
				border-radius: 4px;
				background-color:rgba(0,0,0,0.3)
			}
			view:last-of-type{
				position: absolute;
				right: 0;
				top: 0;
				color: white;
				font-size: 0.9em;
				border-radius: 4px;
				background-color:rgba(0,0,0,0.3)
			}
		}
		>view:last-of-type{
			font-size:1.2em;
			// 一行折行隐藏 ...代替
			white-space:nowrap;
			overflow: hidden;
			text-overflow: ellipsis;
		}
	}
</style>
# 弹出层
popup
vue  this.$refs

<template>
	<view>
		<!-- popup 弹出层 -->
		<!-- ref 绑定子元素 方便 再父元素 调用到子元素的方法 -->
		<!-- ref绑定后找子元素对象  this.$refs.popup  绑定的名称 -->
		<uni-popup ref="popup" type="top">
			<view style="background-color: white;font-size: 35rpx;padding: 10rpx;">
				<!-- 我是弹出层的内容 -->
				<image src="/static/c1.png" mode=""></image>
			</view>
		</uni-popup>
		<!-- 预置样式 提示message -->
		<!-- 代码执行过程中 ref会被覆盖 这里就不改名了 -->
		<uni-popup ref="popup" type="message">
			<uni-popup-message type="success" message="恭喜你成功了!" :duration="2000"></uni-popup-message>
		</uni-popup>
		<uni-popup ref="popup" type="share">
			<uni-popup-share title="分享到" @select="select"></uni-popup-share>
		</uni-popup>
		<!-- 制作一个按钮 点击触发弹出层 -->
		<button type="primary" size="mini" @click="clickOpen">点击这里</button>
	</view>
</template>
<script>
	export default {
		methods:{
			clickOpen(){
				// 找到uni-popup组件 ref绑定找
				console.log(this.$refs.popup)
				// 弹出层的效果
				this.$refs.popup.open()
			},
			select(e){
				// index 通过下标 选择对应的分享
				console.log(e)
			}
		}
	}
</script>
<style scoped>
</style>