纯私人class,公开文章是方便置顶.... 

<template>
	<view>

        <!-- 自定义导航栏 占位空间 -->
		<view class="navigationStyleCustomHeight alwaysOnTopBox0 bgColorForTheme"></view>
		
		<!-- 自定义导航栏 -->
		<view class="alwaysOnTopBox1 rowSpaceBetween colAlignItemsCenter bgColorForTheme colorWhite paddingCol10  paddingRow10">
			<view class="colInner" @click="$fns.goBack">
				<uni-icons type="back" color="white" size="28"></uni-icons>
			</view>
			<view class="colInner fontSize16 weightBold">
				我的账号
			</view>
			<view class="colInner opacity0">
				<uni-icons type="back" color="white" size="28"></uni-icons>
			</view>
		</view>




		
		<!-- 自定义导航栏 (系统组件) -->
		<view class="alwaysOnTopBox1 myNavBar">
			<uni-nav-bar shadow title="UNIAPP示例" leftIcon="back" rightIcon="search" @clickLeft="goBack" @clickRight="goSearch"></uni-nav-bar>
		</view>
		
		
		
		
		<!-- Tab标签头部 -->
		<view class="bgColorWhite">
			<view class="TopTabs rowSpaceEvenly">
				
				<view class="oneTab" :class="{'active': showingTab == 0}" @click="showingTab = 0">
					<text>全部</text>
				</view>
				
				<view class="oneTab" :class="{'active': showingTab == 1}" @click="showingTab = 1">
					<text>未处理</text>
				</view>
				
				<view class="oneTab" :class="{'active': showingTab == 2}" @click="showingTab = 2">
					<text>已完成</text>
				</view>
				
			</view>
		</view>
		
 
 
		<!-- Tab标签内容容器 -->
		<swiper class="swiper" :indicator-dots="false" :autoplay="false" @change="swiperChanged"
			:current="showingTab" :style="{'height': height}">
 
			<swiper-item>
				<!-- .oneDom容器 实际高度 会赋值给swiper作为高度 -->
				<view class="oneDom-0">
					第1个列表
				</view>
			</swiper-item>
 
			<swiper-item>
				<view class="oneDom-1">
					第2个列表
				</view>
			</swiper-item>
 
			<swiper-item>
				<view class="oneDom-2">
					第3个列表
				</view>
			</swiper-item>
 
		</swiper>
		
		
		
		
		
		
		
		
		
		<!-- 底部固定按钮 -->
		<view class="alwaysAtBottomFullRow">
		    <view class="box paddingCol20">
		        <view class="buttonForTheme">
		            确定
		        </view>
		    </view>
		</view>
		
		
		
		
		<!-- 系统错误 -->
		<view class="positionFixed zIndex4 d-flex justify-content-center align-items-center bgColorGray opacity80 colorWhite fontSize18" style="top: 0; right: 0; bottom: 0; left: 0;" v-show="sys_error_msg != ''">
			<view class="paddingRow10">
				{{sys_error_msg}}
			</view>
		</view>
		
		

	</view>
</template>

<script>
	export default {
		data() {
			return {
				// 系统参数
				api: this.$store.getters.getApi,
				token: this.$store.getters.getToken,
				
				// 系统错误
				sys_error_msg: '',
				
				// 正在显示的标签页下标
				showingTab: 0,
				
				// 预设的swiper高度, 80%屏幕高度
				height: '80vh',
				
				
				// 列表数量
				tabsTotal: 3,
				
				// 分页信息 - 【参数】列表数量  this.tabsTotal无法及时传入,需手动传入
				pagination: this.get_init_pagination(3),
				
				
			}
		},
		
		computed: {
			
			
		},
		
		onLoad (p) {
			// 如果没有XX参数
			if (!p.hasOwnProperty('xx')) {
				// ...
			}
		},
		
		onShow () {
			
			// 重建列表
			this.rebuild_lists()
			
			// 动态设置Swiper高度
			this.setH()
			
		},
		
		onReachBottom() {
		
			// 触底刷新
			this.get_list()
		
		},
		
		methods: {
			
			// 返回
			goBack() {
				uni.navigateBack()
			},
			
			// 页面跳转
			goPage (name) {
				uni.navigateTo({
					url: '/pages/' + name + '/' + name
				})
			},
			
			
			// 信息提示
			showError(e, icon = 'none') {
				uni.showToast({
					icon: icon,
					title: e
				})
			},
			
			
			// 显示系统错误
			systemShowError (msg) {
				this.sys_error_msg = msg
			},
			
			
			// 显示loading
			showLoading (title = '') {
				uni.showLoading({
					title: title,
					mask: true
				})
			},
			
			// 隐藏loading
			hideLoading () {
				uni.hideLoading()
			},
			
			
			// 获取图片地址
			get_img_src(url) {
				let res = ''
				if (/^[\\/]+/.test(url)) {
					// 斜杠开头
					res = this.$store.getters.getApi + '/factory' + url
			
				} else {
					res = this.$store.getters.getApi + '/factory/profile/' + url
				}
			
				return res
			},
			
			
			// 重建所有列表
			rebuild_lists () {
				// 清空
				this.pagination = this.get_init_pagination(this.tabsTotal)
				
				// 重建
				this.get_list(null, false)
				
				
				this.setH()
			},
			
			// 初始化的分页情况 -- tabs列表数量
			get_init_pagination(tabs = 1) {
				console.log('[初始化分页]', String(tabs))
				let p = {
					// 每页大小
					pageSize: 10,
			
					// 当前分页页码
					pageNums: [],
			
					// 各列表的总页数
					pageNumsTotal: [],
			
					// 各列表的总记录数量
					rowsTotal: [],
			
					// 各列表
					lists: [],
				}
			
				for (var i = 0; i < tabs; i++) {
					p.pageNums.push(0)
					p.pageNumsTotal.push(null)
					p.rowsTotal.push(null)
					p.lists.push([])
				}
			
				console.log('[分页]', JSON.stringify(p))
				return p
			},
			
			
			/**
			 *  获取数据
			 * 
			 * @param index 列表下标
			 * @param auto_next 自动获取后续列表
			 */
			get_list(index = null, auto_next = false) {
				// 先刷新高度
				this.setH()
				
				// 默认搜索当前tab的列表
				if (index === null) {
					index = this.showingTab
				}
			
				// 检查是否最后一页
				let pagi = this.pagination
				if (pagi.pageNumsTotal[index] !== null && pagi.pageNums[index] == pagi.pageNumsTotal[index]) {
					if (pagi.pageNums[index] > 1) {
						this.showError('已是最后一页')
					}
					return
				}
			
				// 开始获取
				let d = {
					
				}
				let u = this.api + '/api/xxxx'
				console.log('==================================================================')
				console.log('[提交数据]', JSON.stringify(d))
				console.log('[提交地址]', u)
			
			
				uni.showLoading()
				uni.request({
					url: u,
					method: 'GET',
					dataType: 'JSON',
					header: {
						'Authorization': this.token
					},
					data: d,
					success: (res) => {
						uni.hideLoading()
						console.log(JSON.stringify(res.data))
						if (res.statusCode != 200) {
							uni.showToast({
								icon: 'none',
								title: res.errMsg
							})
							return
						}
			
						if (res.data.code != 200) {
							uni.showToast({
								icon: 'none',
								title: res.data.msg
							})
							return
						}
			
						// 成功
			
						// 记录总数
						if (this.pagination.rowsTotal[index] === null) {
							this.pagination.rowsTotal[index] = parseInt(res.data.total)
						}
			
						// 计算总页码
						if (this.pagination.pageNumsTotal[index] === null) {
							let tp = Math.ceil(parseInt(res.data.total) / this.pagination.pageSize)
							this.pagination.pageNumsTotal[index] = tp
						}
			
			
						if (res.data.rows.length) {
							// 记录当前页码
							this.pagination.pageNums[index] += 1
			
							let cur_rows = res.data.rows
							
							// 列表拼接
							this.pagination.lists[index] = this.pagination.lists[index].concat(cur_rows)
						}
			
			
						
						this.setH()
						
						// 递增
						if (auto_next) {
							let pn = index + 1
							console.log('[递增]', String(pn), '[Tabs]', this.tabsTotal)
							if (pn < this.tabsTotal) {
								// 自增查询
								this.get_list(pn, true)
							}
						}
			
					},
					fail: (e) => {
						uni.hideLoading()
						console.log(JSON.stringify(e))
						uni.showToast({
							icon: 'none',
							title: '请求失败'
						})
					}
				})
			
			},
			
			
			// 设置高度
			setH() {
				// 延时设置高度 -- 一定要延时,否则报错 - 300毫秒一般都够了
				setTimeout(() => {
					// 节点查询
					const query = uni.createSelectorQuery().in(this)
					// 开始
					query.select('.oneDom-' + this.showingTab).boundingClientRect(data => {
						// 获取DOM的高度, 单位是像素
						let h = data.height
						
						// 最起码500px
						h = Math.max(500, h)
						
						// 补上单位
						h += 'px'
						
						// 实际高度赋值给swiper
						this.height = h
						// console.log('【动态设置高度】', h)
						
					}).exec()
				}, 300)
			},

			// 左右滑动时
			swiperChanged(e) {
				// 记录切换的Tab序号
				this.showingTab = e.detail.current
				
				// 动态设置高度
				this.setH()
			},
			
			
			
			
				
			
			// METHODS结束
		}
	}
</script>


<style scoped>
	.myNavBar /deep/ .uni-nav-bar-text {
		font-size: 16px !important;
		font-weight: bold;
	}
</style>

<style>
	
	/* 默认Tab样式 */
	.oneTab {
		color: black;
		padding-top: 10px;
		padding-bottom: 10px;
		position: relative;
	}
 
	.oneTab:after {
		content: '';
		position: absolute;
		left: 30%;
		bottom: 0;
		width: 40%;
		border-bottom: 1px solid transparent;
	}
 
 
	/* active激活状态的Tab样式 */
	.oneTab.active {
		color: #FF8D1A;
	}
 
	.oneTab.active:after {
		border-bottom: 1px solid #FF8D1A;
	}
 
	
</style>

制作套壳APP

1. 新建uniapp项目(可以不使用uni-ui)
2. 修改 \pages\index\index.vue,在template的view中添加:
   <web-view src="https://xxx.com/xxx/"></web-view>
3. OK
4. 可以隐藏index.vue的顶部导航栏,或者全屏
   pages.json >> globalStyle >> 添加"navigationStyle": "custom"

自定义字体

1. 放置ttf文件到\static\xx.ttf
2. 参考 \static\customicons.css 修改ttf位置
3. 修改 \app.vue,引入上面的css文件
4. 在各自的pages的vue文件的style中使用 .xx { font-family: 'xx'; }
5. OK, 不行就重新编译app

全局通用css样式

修改 \app.vue,在style中引入,格式:
@import '@/static/xx.css';

全局函数、全局方法

\common\fn.js

function fn1 (param) { return 'result1'; }
function fn2 (param) { return 'result2'; }

export default {
    fn1,
    fn2
}

\main.js

import Vue from 'vue'
import App from './App'
import fn from './common/fn.js'

Vue.config.productionTip = false
Vue.prototype.$fn = fn

App.mpType = 'app'

const app = new Vue({
    fn,
    ...App
})
app.$mount()
 

\pages\xx\xx.vue

let xx = this.$fn.fn1( 'anything' )

全局变量定义、修改、读取

登录状态、退出登录

本地存储 (登录-记住我)

Tabbar底部标签栏实现

顶部导航栏修改、自定义、添加右边的按钮

页面下拉刷新

图片懒加载

页面触底刷新、下一页、分页

Ajax交互 - 文字

Ajax交互 - 文字 + 图片视频 (文件上传)

Ajax交互 - 文字 + PDF文件上传(或其他)

修改内置组件样式

自定义图标

App图标设置

App启动页

alert提示

confirm确认提示框

饼状图、柱状图、统计图表

获取短字符串 (后面星号代替)

// 获取短字符串 (后面星号代替)
get_short_string (str, max_length = 10, separator = '*') {
    // 字符串转数组
    let res = String(str)
    let arr = res.split('')
    
    // 星号长度
    let separator_length = 3
    
    // 正数
    max_length = Math.max(0, parseInt(max_length))
    
    // 星号除外的长度
    let cut_length = Math.max(0, max_length - separator_length)
    
    if (arr.length > max_length) {
        // 如果长度符合
        res = ''
        for (let i in arr) {
            if (i < cut_length) {
                // 切
                res += arr[i]
            }
        }
        // 拼接
        res += separator.repeat(separator_length)
    }
    return res
},

// 获取短字符串 (中间用星号代替)
get_short_string_two_sides (str, max_length = 10, side_length = 3, separator = '*') {
    // 规范
    max_length =  Math.max(0, parseInt(max_length))
    side_length = Math.max(0, parseInt(side_length))        // 两边明文长度
    
    // 字符串转数组
    let res = String(str)
    let arr = res.split('')
    
    // 直接返回短字符串
    if (arr.length <= max_length || arr.length < 4) {
        return res
    }
    
    // 调整两边明文长度
    let half_length = Math.ceil( max_length / 2 )             // 一半长度
    side_length = Math.min(side_length, half_length - 1)    // 两边明文长度 要小于一半长度
    
    // 星号开始下标
    let separator_start_index = side_length
    // 星号结束下标
    let separator_end_index = arr.length - side_length - 1
    // 星号长度
    let separator_length = max_length - side_length - side_length
    
    // 正数
    separator_length = Math.max(0, separator_length)
    
    // 开切
    res = ''
    let left = ''
    let right = ''
    for (let i in arr) {
        if (i < separator_start_index) {
            // 切
            left += arr[i]
        }
        
        if (i > separator_end_index) {
            // 切
            right += arr[i]
        }
    }
    // 拼接
    res = left + separator.repeat(separator_length) + right
    
    return res
},

多选 / 单选 - radio checkbox

常见页面 - 标签页切换 - 不同列表切换 (自用class)

<template>
	<view>
 
		<!-- Tab标签头部 -->
		<view class="bgColorWhite">
			<view class="TopTabs rowSpaceEvenly">
				
				<view class="oneTab" :class="{'active': showingTab == 0}" @click="showingTab = 0">
					<text>全部</text>
				</view>
				
				<view class="oneTab" :class="{'active': showingTab == 1}" @click="showingTab = 1">
					<text>未处理</text>
				</view>
				
				<view class="oneTab" :class="{'active': showingTab == 2}" @click="showingTab = 2">
					<text>已完成</text>
				</view>
				
				
				
			</view>
		</view>
		
 
 
		<!-- Tab标签内容容器 -->
		<swiper class="swiper" :indicator-dots="false" :autoplay="false" @change="swiperChanged"
			:current="showingTab" :style="{'height': height}">
 
			<swiper-item>
				<!-- .oneDom容器 实际高度 会赋值给swiper作为高度 -->
				<view class="oneDom-0">
					第1个列表
				</view>
			</swiper-item>
 
			<swiper-item>
				<view class="oneDom-1">
					第2个列表
				</view>
			</swiper-item>
 
			<swiper-item>
				<view class="oneDom-2">
					第3个列表
				</view>
			</swiper-item>
 
		</swiper>
 
	</view>
</template>
 
<script>
	export default {
		data() {
			return {
				// 正在显示的标签页下标
				showingTab: 0,
 				
				// 预设的swiper高度, 80%屏幕高度
				height: '80vh'
			}
		},
 
		// 页面OK以后
		onLoad() {
 
			// 动态设置Swiper高度
			this.setH()

		},
 
		methods: {
			
			// 设置高度
			setH() {
				// 延时设置高度 -- 一定要延时,否则报错 - 300毫秒一般都够了
				setTimeout(() => {
					// 节点查询
					const query = uni.createSelectorQuery().in(this)
					// 开始
					query.select('.oneDom-' + this.showingTab).boundingClientRect(data => {
						// 获取DOM的高度, 单位是像素
						let h = data.height
						h = Math.max(500, h)
						
						// 补上单位
						h += 'px'
						
						// 实际高度赋值给swiper
						this.height = h
						console.log('【动态设置高度】', h)
					}).exec()
				}, 300)
			},
 
			// 左右滑动时
			swiperChanged(e) {
				this.showingTab = e.detail.current
				
				// 动态设置高度
				this.setH()
			}
 
		}
	}
</script>
 
<style>
	/* 默认Tab样式 */
	.oneTab {
		color: black;
		padding-top: 10px;
		padding-bottom: 10px;
		position: relative;
	}
 
	.oneTab:after {
		content: '';
		position: absolute;
		left: 30%;
		bottom: 0;
		width: 40%;
		border-bottom: 1px solid transparent;
	}
 
 
	/* active激活状态的Tab样式 */
	.oneTab.active {
		color: #FF8D1A;
	}
 
	.oneTab.active:after {
		border-bottom: 1px solid #FF8D1A;
	}
 
</style>

更多推荐