345 lines
8.9 KiB
JavaScript
345 lines
8.9 KiB
JavaScript
|
// 引入事件模块 https://github.com/GravityC/SPage
|
|||
|
const SEvent = require('SEvent.js')
|
|||
|
wx.$event = {
|
|||
|
on(eventName, handler) {
|
|||
|
return SEvent.getEvent(eventName).on(handler)
|
|||
|
},
|
|||
|
once(eventName, handler) {
|
|||
|
SEvent.getEvent(eventName).once(handler)
|
|||
|
},
|
|||
|
emit(eventName) {
|
|||
|
const args = Array.from(arguments).slice(1)
|
|||
|
SEvent.getEvent(eventName).emit(...args)
|
|||
|
},
|
|||
|
off(nameOrId, handler) {
|
|||
|
if(handler && typeof (handler) === 'function'){
|
|||
|
SEvent.getEvent(nameOrId).off(handler)
|
|||
|
}else{
|
|||
|
SEvent.off(nameOrId)
|
|||
|
}
|
|||
|
},
|
|||
|
remove(eventName) {
|
|||
|
SEvent.removeEvent(eventName)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 引入request模块
|
|||
|
const SRequest = require('SRequest.js')
|
|||
|
const $http = new SRequest()
|
|||
|
wx.$http = $http
|
|||
|
wx.$request = $http.request.bind($http)
|
|||
|
wx.$get = $http.get.bind($http)
|
|||
|
wx.$post = $http.post.bind($http)
|
|||
|
wx.$put = $http.put.bind($http)
|
|||
|
wx.$delete = $http.delete.bind($http)
|
|||
|
|
|||
|
|
|||
|
/* ----------------------------------------------------------------------------- */
|
|||
|
wx.$pages = {}
|
|||
|
// 获取当前页面实例
|
|||
|
wx.$getCurPage = function() {
|
|||
|
return getCurrentPages()[getCurrentPages().length - 1]
|
|||
|
}
|
|||
|
|
|||
|
// 获取当前页面实例对应的页面名
|
|||
|
wx.$getCurPageName = function() {
|
|||
|
return wx.$getCurPage().$name
|
|||
|
}
|
|||
|
|
|||
|
// $place与$take,$take调用完即删除引用
|
|||
|
let channel = {}
|
|||
|
wx.$place = function(id, value) {
|
|||
|
channel[id] = value
|
|||
|
}
|
|||
|
|
|||
|
wx.$take = function(id) {
|
|||
|
const v = channel[id]
|
|||
|
channel[id] = null
|
|||
|
return v
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 封装wx.navigateTo
|
|||
|
* @url {string} - 跳转路径
|
|||
|
* @query {object} - 携带参数
|
|||
|
*/
|
|||
|
wx.$route = function(url, query) {
|
|||
|
const page = getPage(url)
|
|||
|
query = query || {}
|
|||
|
query.from = wx.$getCurPageName() // Page || Component
|
|||
|
// 若page已加载可调用onNavigate方法
|
|||
|
if (page && page.onNavigate) {
|
|||
|
page.onNavigate(query)
|
|||
|
}
|
|||
|
url = url + '?' + parseQuery(query)
|
|||
|
wx.navigateTo({
|
|||
|
url
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// -----------------------------以下是工具函数----------------------
|
|||
|
|
|||
|
//装饰器
|
|||
|
//@afterOrigin {Boolean} - true:装饰函数在原函数之后触发
|
|||
|
const decorator = function(originFn, decorateFn, afterOrigin) {
|
|||
|
const origin = originFn
|
|||
|
originFn = function(args) {
|
|||
|
if (afterOrigin) {
|
|||
|
if (origin) origin.call(this, args)
|
|||
|
decorateFn.call(this, args)
|
|||
|
} else {
|
|||
|
decorateFn.call(this, args)
|
|||
|
if (origin) origin.call(this, args)
|
|||
|
}
|
|||
|
}
|
|||
|
return originFn
|
|||
|
}
|
|||
|
|
|||
|
// 解析query对象成string
|
|||
|
const parseQuery = function(query) {
|
|||
|
return Object.keys(query).map(k => `${k}=${query[k]}`).join('&')
|
|||
|
}
|
|||
|
|
|||
|
// 从url中得到pageName
|
|||
|
const getPageName = function(url) {
|
|||
|
url = url.includes('?') ? url.split('?')[0] : url
|
|||
|
const arr = url.split('/')
|
|||
|
return arr[arr.length - 1]
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @str - pageName或者url
|
|||
|
*/
|
|||
|
const getPage = function(str) {
|
|||
|
const name = str.includes('/') ? getPageName(str) : str
|
|||
|
return wx.$pages[name]
|
|||
|
}
|
|||
|
|
|||
|
// 判断是否是空对象
|
|||
|
const isEmpty = function(obj) {
|
|||
|
return !Object.keys(obj).length
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 扩展computed计算属性
|
|||
|
*/
|
|||
|
const extendComputed = function(option) {
|
|||
|
let page
|
|||
|
// 为$setData方法响应computed
|
|||
|
option.$setData = function(obj) {
|
|||
|
this.setData(obj)
|
|||
|
page = this // 绑定page实例
|
|||
|
const needUpdate = calcComputed() // 将需要改变的computed属性添加到接下来要setData的对象中
|
|||
|
if (!isEmpty(needUpdate)) {
|
|||
|
this.setData(needUpdate)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const computed = option.computed || {}
|
|||
|
const computedKeys = Object.keys(computed)
|
|||
|
let computedCache = {}
|
|||
|
|
|||
|
// 计算需更改的计算属性
|
|||
|
const calcComputed = function(isInit) {
|
|||
|
const needUpdate = {}
|
|||
|
const that = isInit ? option : page
|
|||
|
for (const key of computedKeys) {
|
|||
|
const value = computed[key].call(that)
|
|||
|
if (value !== computedCache[key]) needUpdate[key] = computedCache[key] = value
|
|||
|
if (isInit) option.data[key] = needUpdate[key] // 初始化操作
|
|||
|
}
|
|||
|
return needUpdate
|
|||
|
}
|
|||
|
|
|||
|
// 页面unload时清空computedCache
|
|||
|
option.onUnload = decorator(option.onUnload, function() {
|
|||
|
computedCache = {}
|
|||
|
})
|
|||
|
|
|||
|
calcComputed(true);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 为所有Page和Component扩展方法
|
|||
|
*/
|
|||
|
const extendFunctions = function(option) {
|
|||
|
option.$route = wx.$route
|
|||
|
option.$place = wx.$place
|
|||
|
option.$take = wx.$take
|
|||
|
// 封装wx.request
|
|||
|
option.$request = wx.$request
|
|||
|
option.$get = wx.$get
|
|||
|
option.$post = wx.$post
|
|||
|
option.$put = wx.$put
|
|||
|
option.$delete = wx.$delete
|
|||
|
// 事件机制
|
|||
|
option.$on = function(eventName, handler){
|
|||
|
this.$listeners = this.$listeners || []
|
|||
|
this.$listeners.push(wx.$event.on(eventName, handler))
|
|||
|
}
|
|||
|
option.$once = wx.$event.once
|
|||
|
option.$emit = wx.$event.emit
|
|||
|
option.$off = wx.$event.off
|
|||
|
option.$remove = wx.$event.remove
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* -------------扩展App-------------------
|
|||
|
*/
|
|||
|
let initPageObject
|
|||
|
let initCompObject
|
|||
|
const extendApp = function() {
|
|||
|
const originApp = App
|
|||
|
App = function(option) {
|
|||
|
if (option.$mixinP) {
|
|||
|
initPageObject = option.$mixinP
|
|||
|
}
|
|||
|
|
|||
|
if (option.$mixinC) {
|
|||
|
initCompObject = option.$mixinC
|
|||
|
}
|
|||
|
|
|||
|
originApp(option)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* -------------扩展Page----------------
|
|||
|
*/
|
|||
|
const extendPage = function() {
|
|||
|
const originPage = Page
|
|||
|
Page = function(option) {
|
|||
|
// 混合app.$mixinP
|
|||
|
if (initPageObject) {
|
|||
|
const hooks = ['onLoad', 'onShow', 'onReady', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage', 'onPageScroll', 'onResize', 'onTabItemTap']
|
|||
|
for (const k in initPageObject) {
|
|||
|
if (hooks.includes(k)) {
|
|||
|
option[k] = decorator(option[k], initPageObject[k])
|
|||
|
} else if (k === 'data') {
|
|||
|
option.data = Object.assign({}, initPageObject.data, option.data)
|
|||
|
} else if (!option.hasOwnProperty(k)) {
|
|||
|
option[k] = initPageObject[k]
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 若定义了$name, 则添加到wx.$pages中
|
|||
|
if (option.$name) {
|
|||
|
wx.$pages[option.$name] = option
|
|||
|
} else {
|
|||
|
option.$name = 'unKnow' //此处强行给$name赋值,为了后续区分是Page还是Component
|
|||
|
}
|
|||
|
|
|||
|
// 添加$status属性
|
|||
|
option.$status = {
|
|||
|
isFirstShow: true
|
|||
|
}
|
|||
|
// 是否已执行过onNavigate函数
|
|||
|
option.$$isNavigated = false
|
|||
|
|
|||
|
// 扩展computed属性
|
|||
|
extendComputed(option)
|
|||
|
// 扩展方法
|
|||
|
extendFunctions(option)
|
|||
|
|
|||
|
// 装饰onNavigate
|
|||
|
option.onNavigate = decorator(option.onNavigate, function(query) {
|
|||
|
option.$$isNavigated = true
|
|||
|
})
|
|||
|
|
|||
|
// 装饰onLoad
|
|||
|
option.onLoad = decorator(option.onLoad, function(query) {
|
|||
|
// 若页面有onNavigate方法但还没运行,则运行onNavigate方法
|
|||
|
if (option.onNavigate && !option.$$isNavigated) {
|
|||
|
option.onNavigate(query)
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
// 装饰onShow
|
|||
|
option.onShow = decorator(option.onShow, function() {
|
|||
|
this.$status.isFirstShow = false
|
|||
|
}, true)
|
|||
|
|
|||
|
// 隐藏页面时隐藏标题栏加载动画(坑爹的微信官方bug)
|
|||
|
option.onHide = decorator(option.onHide, function() {
|
|||
|
wx.hideNavigationBarLoading()
|
|||
|
})
|
|||
|
|
|||
|
// 装饰onUnload
|
|||
|
option.onUnload = decorator(option.onUnload, function(){
|
|||
|
// 卸载本页面的监听器
|
|||
|
if (this.$listeners && this.$listeners.length) {
|
|||
|
for (const id of this.$listeners) {
|
|||
|
wx.$event.off(id)
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
//原生Page构造
|
|||
|
originPage(option)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* --------------------------------------------扩展Component
|
|||
|
*/
|
|||
|
const extendComponent = function() {
|
|||
|
const originComponent = Component
|
|||
|
Component = function(option) {
|
|||
|
option.methods = option.methods || {}
|
|||
|
// 混合app.$mixinC
|
|||
|
if (initCompObject) {
|
|||
|
const mixinObj = ['properties', 'data', 'observers', 'methods', 'options']
|
|||
|
for (const k in initCompObject) {
|
|||
|
if (k === 'lifetimes' || k === 'pageLifetimes') {
|
|||
|
if (!option[k]) {
|
|||
|
option[k] = initCompObject[k]
|
|||
|
} else {
|
|||
|
for (const h in initCompObject[k]) {
|
|||
|
option[k][h] = decorator(option[k][h], initCompObject[k][h])
|
|||
|
}
|
|||
|
}
|
|||
|
} else if (mixinObj.includes(k)) {
|
|||
|
option[k] = Object.assign({}, initCompObject[k], option[k])
|
|||
|
} else if (!option.hasOwnProperty(k)) {
|
|||
|
option[k] = initCompObject[k]
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// 扩展computed属性
|
|||
|
extendComputed(option)
|
|||
|
// 扩展方法
|
|||
|
extendFunctions(option.methods)
|
|||
|
|
|||
|
option.lifetimes = option.lifetimes || {}
|
|||
|
// 装饰detached
|
|||
|
option.lifetimes.detached = decorator(option.lifetimes.detached, function () {
|
|||
|
// 卸载本组件的监听器
|
|||
|
if (this.$listeners && this.$listeners.length) {
|
|||
|
for (const id of this.$listeners) {
|
|||
|
wx.$event.off(id)
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
// 获取当前页面实例
|
|||
|
option.methods.$getCurPage = wx.$getCurPage
|
|||
|
|
|||
|
// 获取当前页面实例对应的页面名
|
|||
|
option.methods.$getCurPageName = wx.$getCurPageName
|
|||
|
|
|||
|
// 重新定义$setData,便于扩展其他功能
|
|||
|
const originData = option.$setData
|
|||
|
option.methods.$setData = function(obj) {
|
|||
|
return originData.call(this, obj)
|
|||
|
}
|
|||
|
//原生Component构造
|
|||
|
originComponent(option)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
module.exports = (function() {
|
|||
|
extendApp()
|
|||
|
extendPage()
|
|||
|
extendComponent()
|
|||
|
}())
|