├── .gitignore ├── README.md ├── app.js ├── app.json ├── app.wxss ├── components └── statusLayout │ ├── statusLayout.js │ ├── statusLayout.json │ ├── statusLayout.wxml │ └── statusLayout.wxss ├── img ├── empty.png ├── error.png └── loading.png ├── pages └── index │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── preview └── preview.gif └── utils └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | *swp 2 | *~ 3 | .idea 4 | node_modules 5 | npm-debug.log 6 | jsconfig.json 7 | project.config.json 8 | .vscode/ 9 | typings/ 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wx-statuslayout 2 | 微信小程序页面状态切换组件, 如果对您有帮助的话, 就赏个star吧~ 3 | 4 | ## 效果图 5 | 6 | ![](https://raw.githubusercontent.com/zzjian/wx-statuslayout/0c87f17bd07381d82192200f1434aa74b1266872/preview/preview.gif) 7 | 8 | ## 自定义属性 9 | - `rootStyle` 根容器样式, 可用来设置组件宽高等 10 | - `status` 默认状态 11 | - `emptyImage` 无数据时的图片 12 | - `emptyText` 无数据时的文案 13 | - `emptyImageWidth` 无数据时图片宽度 14 | - `emptyImageHeight` 无数据时图片高度 15 | - `errorImage` 发生错误时的图片 16 | - `errorText` 发生错误时的文案 17 | - `errorImageWidth` 错误图片宽 18 | - `errorImageHeight` 错误图片高 19 | - `loadingText` 加载文案 20 | - `loadingImage` 加载图片 21 | - `loadingImageWidth` 加载图片宽 22 | - `loadingImageHeight` 加载图片高 23 | 24 | ## 使用 25 | 1. 将`statusLayout`组件拷贝到自己项目中 26 | 2. 修改`statuslayout.js` 中的属性默认值, 状态图片、文案及图片宽高 27 | 3. 在需要使用的页面json文件中添加引用 28 | ``` json 29 | "usingComponents": { 30 | "statusLayout": "../../components/statusLayout/statusLayout" 31 | } 32 | ``` 33 | 4. 在页面wxss文件中添加`statusLayout`布局 34 | ``` json 35 | 36 | //内容 37 | 38 | {{item}} 39 | 40 | 41 | ``` 42 | 43 | 5. 在js文件中使用 44 | 45 | 1. 获取statusLayout组件对象 `statusLayout = this.selectComponent("#statusLayout")` 46 | 47 | 2. 切换布局`(两种切换布局的方法)` 48 | 49 | - 一个方法通过不同参数切换 50 | ```js 51 | statusLayout.setStatus("LOADING") 52 | 53 | statusLayout.setStatus("CONTENT") 54 | 55 | statusLayout.setStatus("ERROR") 56 | 57 | statusLayout.setStatus("EMPTY") 58 | ``` 59 | - 直接调不同的方法切换 60 | 61 | ``` js 62 | statusLayout.showLoading() 63 | 64 | statusLayout.showContent() 65 | 66 | statusLayout.showError() 67 | 68 | statusLayout.showEmpty() 69 | 70 | ``` 71 | 3. 绑定点击重新加载的回调 72 | ``` js 73 | 74 | 75 | //testStatusLayout 为页面js文件中加载数据的方法 76 | ``` 77 | 78 | ### 在不同页面设置不同的状态图片及文案等 79 | ``` js 80 | 81 | //内容 82 | 83 | ``` 84 | 85 | 86 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | // 展示本地存储能力 5 | var logs = wx.getStorageSync('logs') || [] 6 | logs.unshift(Date.now()) 7 | wx.setStorageSync('logs', logs) 8 | 9 | // 登录 10 | wx.login({ 11 | success: res => { 12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 13 | } 14 | }) 15 | // 获取用户信息 16 | wx.getSetting({ 17 | success: res => { 18 | if (res.authSetting['scope.userInfo']) { 19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 20 | wx.getUserInfo({ 21 | success: res => { 22 | // 可以将 res 发送给后台解码出 unionId 23 | this.globalData.userInfo = res.userInfo 24 | 25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 26 | // 所以此处加入 callback 以防止这种情况 27 | if (this.userInfoReadyCallback) { 28 | this.userInfoReadyCallback(res) 29 | } 30 | } 31 | }) 32 | } 33 | } 34 | }) 35 | }, 36 | globalData: { 37 | userInfo: null 38 | } 39 | }) -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages":[ 3 | "pages/index/index" 4 | ], 5 | "window":{ 6 | "backgroundTextStyle":"light", 7 | "navigationBarBackgroundColor": "#fff", 8 | "navigationBarTitleText": "WeChat", 9 | "navigationBarTextStyle":"black" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | width: 100%; 5 | position: absolute 6 | } 7 | -------------------------------------------------------------------------------- /components/statusLayout/statusLayout.js: -------------------------------------------------------------------------------- 1 | // components/statusLayout/statusLayout.js 2 | Component({ 3 | /** 4 | * 组件的属性列表 5 | */ 6 | properties: { 7 | rootStyle: { 8 | type: String, 9 | value:'' 10 | }, 11 | status: { 12 | type: String, 13 | value: 'CONTENT', //LOADING、CONTENT、EMPTY、ERROR 14 | observer: function (newVal, oldVal) { 15 | console.log(newVal) 16 | if (newVal == oldVal) return 17 | this.setStatus(newVal) 18 | } 19 | }, 20 | emptyImage:{ 21 | type: String, 22 | value: '../../img/empty.png' 23 | }, 24 | emptyText: { 25 | type: String, 26 | value: '没有数据哦!' 27 | }, 28 | emptyImageWidth: { 29 | type: Number, 30 | value: 64 31 | }, 32 | emptyImageHeight: { 33 | type: Number, 34 | value: 64 35 | }, 36 | errorImage: { 37 | type: String, 38 | value: '../../img/error.png' 39 | }, 40 | errorText: { 41 | type: String, 42 | value: '操作失败, 请稍后重试!' 43 | }, 44 | errorImageWidth: { 45 | type: Number, 46 | value: 64 47 | }, 48 | errorImageHeight: { 49 | type: Number, 50 | value: 64 51 | }, 52 | loadingText:{ 53 | type: String, 54 | value: '加载中, 请稍后!' 55 | }, 56 | loadingImage: { 57 | type: String, 58 | value: '../../img/loading.png' 59 | }, 60 | loadingImageWidth: { 61 | type: Number, 62 | value: 40 63 | }, 64 | loadingImageHeight: { 65 | type: Number, 66 | value: 40 67 | }, 68 | }, 69 | 70 | /** 71 | * 组件的初始数据 72 | */ 73 | data: { 74 | statusText: '', 75 | statusImage: '', 76 | loadingAnimation:'', 77 | imgWidth:100, 78 | imgHeight: 100, 79 | }, 80 | 81 | /** 82 | * 组件的方法列表 83 | */ 84 | methods: { 85 | setStatus: function(status) { 86 | switch(status) { 87 | case 'LOADING': 88 | this.showLoading() 89 | break 90 | case 'EMPTY': 91 | this.showEmpty() 92 | break 93 | case 'ERROR': 94 | this.showError() 95 | break 96 | case 'CONTENT': 97 | this.showContent() 98 | break 99 | default: 100 | console.log("error: 未找到该status") 101 | break 102 | } 103 | }, 104 | showLoading: function(){ 105 | this.setData({ 106 | status: "LOADING", 107 | statusText: this.properties.loadingText, 108 | statusImage: this.properties.loadingImage, 109 | imgWidth: this.properties.loadingImageWidth, 110 | imgHeight: this.properties.loadingImageHeight 111 | }) 112 | }, 113 | showEmpty: function(){ 114 | this.setData({ 115 | status: "EMPTY", 116 | statusText: this.properties.emptyText, 117 | statusImage: this.properties.emptyImage, 118 | imgWidth: this.properties.emptyImageWidth, 119 | imgHeight: this.properties.emptyImageHeight 120 | }) 121 | }, 122 | showError: function(){ 123 | this.setData({ 124 | status: "ERROR", 125 | statusText: this.properties.errorText, 126 | statusImage: this.properties.errorImage, 127 | imgWidth: this.properties.errorImageWidth, 128 | imgHeight: this.properties.errorImageHeight 129 | }) 130 | }, 131 | showContent: function(){ 132 | this.setData({ 133 | status: "CONTENT" 134 | }) 135 | }, 136 | onClickListener: function(res) { 137 | this.triggerEvent('OnClickListener', { status: this.data.status }, {}) 138 | } 139 | } 140 | }) 141 | -------------------------------------------------------------------------------- /components/statusLayout/statusLayout.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /components/statusLayout/statusLayout.wxml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /components/statusLayout/statusLayout.wxss: -------------------------------------------------------------------------------- 1 | /* components/statusLayout/statusLayout.wxss */ 2 | 3 | .status-layout-root{ 4 | width: 100%; 5 | height: 100%; 6 | font-family: PingFangSC-Light; 7 | display: flex; 8 | justify-content: center; 9 | align-items: center; 10 | } 11 | 12 | .status-main{ 13 | text-align: center; 14 | font-size: 14px; 15 | color: #bfbfbf; 16 | letter-spacing: -0.01px; 17 | align-self: center; 18 | font-weight: bold; 19 | } 20 | 21 | .status-main image{ 22 | margin-bottom: 10px; 23 | } 24 | 25 | .status-image{ 26 | width: 137px; 27 | height: 142px; 28 | } 29 | 30 | .status-image-anim{ 31 | animation: weuiLoading 0.6s steps(12, end) infinite; 32 | } 33 | 34 | @keyframes weuiLoading { 35 | 0% { 36 | transform: rotate3d(0, 0, 1, 0deg); 37 | } 38 | 39 | 100% { 40 | transform: rotate3d(0, 0, 1, 360deg); 41 | } 42 | } -------------------------------------------------------------------------------- /img/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzjian/wx-statuslayout/8f7923d3a5507950a088acad4ee06f9b31fab3e0/img/empty.png -------------------------------------------------------------------------------- /img/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzjian/wx-statuslayout/8f7923d3a5507950a088acad4ee06f9b31fab3e0/img/error.png -------------------------------------------------------------------------------- /img/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzjian/wx-statuslayout/8f7923d3a5507950a088acad4ee06f9b31fab3e0/img/loading.png -------------------------------------------------------------------------------- /pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | //获取应用实例 3 | const app = getApp() 4 | var statusLayout 5 | Page({ 6 | data: { 7 | datas: ['测试数据1', '测试数据2', '测试数据3', '测试数据4', '测试数据5'], 8 | system: {} 9 | }, 10 | //事件处理函数 11 | onReady: function(){ 12 | var that = this 13 | statusLayout = this.selectComponent("#statusLayout") 14 | wx.getSystemInfo({ 15 | success: function(res) { 16 | console.log(res) 17 | that.setData({ 18 | system: res 19 | }) 20 | } 21 | }) 22 | }, 23 | onLoad: function () { 24 | }, 25 | testStatusLayout: function(e) { 26 | console.log(e) 27 | statusLayout.showLoading() 28 | // statusLayout.setStatus("LOADING") 29 | setTimeout(function(){ 30 | var num = Math.floor(Math.random() * 10 + 1); //1-10 31 | 32 | if (num <= 3) { 33 | statusLayout.showContent() 34 | // statusLayout.setStatus("CONTENT") 35 | } else if (num <= 7) { 36 | statusLayout.showError() 37 | // statusLayout.setStatus("ERROR") 38 | } else { 39 | statusLayout.showEmpty() 40 | // statusLayout.setStatus("EMPTY") 41 | } 42 | },1000) 43 | } 44 | }) 45 | -------------------------------------------------------------------------------- /pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "测试", 3 | "usingComponents": { 4 | "statusLayout": "../../components/statusLayout/statusLayout" 5 | } 6 | } -------------------------------------------------------------------------------- /pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{item}} 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | .userinfo { 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | } 7 | 8 | .userinfo-avatar { 9 | width: 128rpx; 10 | height: 128rpx; 11 | margin: 20rpx; 12 | border-radius: 50%; 13 | } 14 | 15 | .userinfo-nickname { 16 | color: #aaa; 17 | } 18 | 19 | .usermotto { 20 | margin-top: 200px; 21 | } -------------------------------------------------------------------------------- /preview/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzjian/wx-statuslayout/8f7923d3a5507950a088acad4ee06f9b31fab3e0/preview/preview.gif -------------------------------------------------------------------------------- /utils/util.js: -------------------------------------------------------------------------------- 1 | const formatTime = date => { 2 | const year = date.getFullYear() 3 | const month = date.getMonth() + 1 4 | const day = date.getDate() 5 | const hour = date.getHours() 6 | const minute = date.getMinutes() 7 | const second = date.getSeconds() 8 | 9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 10 | } 11 | 12 | const formatNumber = n => { 13 | n = n.toString() 14 | return n[1] ? n : '0' + n 15 | } 16 | 17 | module.exports = { 18 | formatTime: formatTime 19 | } 20 | --------------------------------------------------------------------------------