提交 9d119821 编写于 作者: fxy060608's avatar fxy060608

refactor navigateBack

上级 7bb0cb54
......@@ -17,16 +17,27 @@ const external = []
if (process.env.UNI_SERVICE === 'legacy') {
input = 'src/platforms/app-plus-nvue/services/index.legacy.js'
output.file = 'packages/uni-app-plus-nvue/dist/index.legacy.js'
} else if (process.env.UNI_SERVICE === 'uni') {
input = 'src/platforms/app-plus/service/uni.js'
output.file = 'packages/uni-app-plus-nvue/dist/uni.js'
} else {
input = 'src/platforms/app-plus/service/index.js'
output.file = 'packages/uni-app-plus-nvue/dist/index.js'
output.format = 'iife'
output.name = 'serviceContext'
output.banner =
`export function createUniInstance(weex, plus, __uniConfig, __uniRoutes, __registerPage, UniServiceJSBridge, getApp, getCurrentPages){
`export function createServiceContext(Vue, weex, plus, __uniConfig, __uniRoutes, UniServiceJSBridge){
var localStorage = plus.storage
var setTimeout = global.setTimeout
var clearTimeout = global.clearTimeout
`
output.footer =
`
var uni = serviceContext.uni
var getApp = serviceContext.getApp
var getCurrentPages = serviceContext.getCurrentPages
var __registerPage = serviceContext.__registerPage
return serviceContext \n}
`
output.footer = '\n return uni$1 \n}'
} else {
external.push('./uni')
}
module.exports = {
......@@ -40,7 +51,7 @@ module.exports = {
'uni-core': path.resolve(__dirname, '../src/core'),
'uni-platform': path.resolve(__dirname, '../src/platforms/' + process.env.UNI_PLATFORM),
'uni-platforms': path.resolve(__dirname, '../src/platforms'),
'uni-shared': path.resolve(__dirname, '../src/shared/util.js'),
'uni-shared': path.resolve(__dirname, '../src/shared/index.js'),
'uni-helpers': path.resolve(__dirname, '../src/core/helpers')
}),
replace({
......
......@@ -6,8 +6,7 @@
"dev:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=h5 node build/build.js",
"build:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.js",
"build:app-plus": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.mp.js",
"build:app:all": "npm run lint && npm run build:app:uni && npm run build:app:nvue && npm run build:app:legacy",
"build:app:uni": "UNI_PLATFORM=app-plus-nvue UNI_SERVICE=uni rollup -c build/rollup.config.app.js",
"build:app:all": "npm run lint && npm run build:app:nvue && npm run build:app:legacy",
"build:app:nvue": "cross-env UNI_PLATFORM=app-plus-nvue rollup -c build/rollup.config.app.js",
"build:app:legacy": "cross-env UNI_PLATFORM=app-plus-nvue UNI_SERVICE=legacy rollup -c build/rollup.config.app.js",
"build:mp-qq": "cross-env UNI_PLATFORM=mp-qq rollup -c build/rollup.config.mp.js",
......
let supportsPassive = false;
try {
const opts = {};
Object.defineProperty(opts, 'passive', ({
get () {
/* istanbul ignore next */
supportsPassive = true;
}
})); // https://github.com/facebook/flow/issues/285
window.addEventListener('test-passive', null, opts);
} catch (e) {}
const hasOwnProperty = Object.prototype.hasOwnProperty;
function isFn (fn) {
......
此差异已折叠。
const method = {
OPTIONS: 'OPTIONS',
GET: 'GET',
HEAD: 'HEAD',
POST: 'POST',
PUT: 'PUT',
DELETE: 'DELETE',
TRACE: 'TRACE',
CONNECT: 'CONNECT'
}
const dataType = {
JSON: 'JSON'
}
const responseType = {
TEXT: 'TEXT',
ARRAYBUFFER: 'ARRAYBUFFER'
}
export const request = {
url: {
type: String,
required: true
},
data: {
type: [Object, String, ArrayBuffer],
validator (value, params) {
params.data = value || ''
}
},
header: {
type: Object,
validator (value, params) {
params.header = value || {}
}
},
method: {
type: String,
validator (value, params) {
value = (value || '').toUpperCase()
params.method = Object.values(method).indexOf(value) < 0 ? method.GET : value
}
},
dataType: {
type: String,
validator (value, params) {
params.dataType = (value || dataType.JSON).toUpperCase()
}
},
responseType: {
type: String,
validator (value, params) {
value = (value || '').toUpperCase()
params.responseType = Object.values(responseType).indexOf(value) < 0 ? responseType.TEXT : value
}
}
import {
isPlainObject
} from 'uni-shared'
const method = {
OPTIONS: 'OPTIONS',
GET: 'GET',
HEAD: 'HEAD',
POST: 'POST',
PUT: 'PUT',
DELETE: 'DELETE',
TRACE: 'TRACE',
CONNECT: 'CONNECT'
}
const dataType = {
JSON: 'JSON'
}
const responseType = {
TEXT: 'TEXT',
ARRAYBUFFER: 'ARRAYBUFFER'
}
const encode = encodeURIComponent
function stringifyQuery (url, data) {
let str = url.split('#')
const hash = str[1] || ''
str = str[0].split('?')
let query = str[1] || ''
url = str[0]
const search = query.split('&').filter(item => item)
query = {}
search.forEach(item => {
item = item.split('=')
query[item[0]] = item[1]
})
for (let key in data) {
if (data.hasOwnProperty(key)) {
if (isPlainObject(data[key])) {
query[encode(key)] = encode(JSON.stringify(data[key]))
} else {
query[encode(key)] = encode(data[key])
}
}
}
query = Object.keys(query).map(item => `${item}=${query[item]}`).join('&')
return url + (query ? '?' + query : '') + (hash ? '#' + hash : '')
}
export const request = {
method: {
type: String,
validator (value, params) {
value = (value || '').toUpperCase()
params.method = Object.values(method).indexOf(value) < 0 ? method.GET : value
}
},
data: {
type: [Object, String, ArrayBuffer],
validator (value, params) {
params.data = value || ''
}
},
url: {
type: String,
required: true,
validator (value, params) {
if (
params.method === method.GET &&
isPlainObject(params.data) &&
Object.keys(params.data).length
) { // 将 method,data 校验提前,保证 url 校验时,method,data 已被格式化
params.url = stringifyQuery(value, params.data)
}
}
},
header: {
type: Object,
validator (value, params) {
params.header = value || {}
}
},
dataType: {
type: String,
validator (value, params) {
params.dataType = (value || dataType.JSON).toUpperCase()
}
},
responseType: {
type: String,
validator (value, params) {
value = (value || '').toUpperCase()
params.responseType = Object.values(responseType).indexOf(value) < 0 ? responseType.TEXT : value
}
}
}
import {
isPlainObject
} from 'uni-shared'
import {
invoke
} from 'uni-core/service/bridge'
import {
onMethod,
invokeMethod
} from '../../platform'
const requestTasks = Object.create(null)
function formatResponse (res, args) {
if (
typeof res.data === 'string' &&
res.data.charCodeAt(0) === 65279
) {
res.data = res.data.substr(1)
}
res.statusCode = parseInt(res.statusCode, 10)
if (isPlainObject(res.header)) {
res.header = Object.keys(res.header).reduce(function (ret, key) {
const value = res.header[key]
if (Array.isArray(value)) {
ret[key] = value.join(',')
} else if (typeof value === 'string') {
ret[key] = value
}
return ret
}, {})
}
if (args.dataType && args.dataType.toLowerCase() === 'json') {
try {
res.data = JSON.parse(res.data)
} catch (e) {}
}
return res
}
onMethod('onRequestTaskStateChange', function ({
requestTaskId,
state,
data,
statusCode,
header,
errMsg
}) {
const {
args,
callbackId
} = requestTasks[requestTaskId]
if (!callbackId) {
return
}
delete requestTasks[requestTaskId]
switch (state) {
case 'success':
invoke(callbackId, formatResponse({
data,
statusCode,
header,
errMsg: 'request:ok'
}, args))
break
case 'fail':
invoke(callbackId, {
errMsg: 'request:fail ' + errMsg
})
break
}
})
class RequestTask {
constructor (id) {
this.id = id
}
abort () {
invokeMethod('operateRequestTask', {
requestTaskId: this.id,
operationType: 'abort'
})
}
offHeadersReceived () {
}
onHeadersReceived () {
}
}
export function request (args, callbackId) {
const {
requestTaskId
} = invokeMethod('createRequestTask', args)
requestTasks[requestTaskId] = {
args,
callbackId
}
return new RequestTask(requestTaskId)
}
import api from 'uni-platform/service/api'
export function unpack (args) {
return args
}
......@@ -7,19 +5,3 @@ export function unpack (args) {
export function invoke (...args) {
return UniServiceJSBridge.invokeCallbackHandler(...args)
}
/**
* 执行内部平台方法
*/
export function invokeMethod (name, ...args) {
return api[name].apply(null, args)
}
/**
* 监听 service 层内部平台方法回调,与 publish 对应
* @param {Object} name
* @param {Object} callback
*/
export function onMethod (name, callback) {
return UniServiceJSBridge.on('api.' + name, callback)
}
import api from 'uni-platform/service/api'
/**
* 执行内部平台方法
*/
export function invokeMethod (name, ...args) {
return api[name].apply(null, args)
}
/**
* 监听 service 层内部平台方法回调,与 publish 对应
* @param {Object} name
* @param {Object} callback
*/
export function onMethod (name, callback) {
return UniServiceJSBridge.on('api.' + name, callback)
}
import * as api from './api/index'
import * as appApi from '../../app-plus/service/api/index'
import * as nvueApi from './api/index'
export default api
export default Object.assign(Object.create(null), appApi, nvueApi)
......@@ -2,35 +2,84 @@ import {
ANI_DURATION
} from './util'
import {
setStatusBarStyle
} from '../../bridge'
let firstBackTime = 0
export function navigateBack ({
delta,
animationType,
animationDuration
}) {
const pages = getCurrentPages()
const len = pages.length - 1
const page = pages[len]
if (page.$page.meta.isQuit) {
if (!firstBackTime) {
firstBackTime = Date.now()
plus.nativeUI.toast('再按一次退出应用')
setTimeout(() => {
firstBackTime = null
}, 2000)
} else if (Date.now() - firstBackTime < 2000) {
plus.runtime.quit()
function quit() {
if (!firstBackTime) {
firstBackTime = Date.now()
plus.nativeUI.toast('再按一次退出应用')
setTimeout(() => {
firstBackTime = null
}, 2000)
} else if (Date.now() - firstBackTime < 2000) {
plus.runtime.quit()
}
}
function backWebview(webview, callback) {
if (!webview.__uniapp_webview) {
return callback()
}
const children = webview.children()
if (!children || !children.length) { // 有子 webview
return callback()
}
const childWebview = children[0]
childWebview.canBack(({
canBack
}) => {
if (canBack) {
childWebview.back() // webview 返回
} else {
callback()
}
} else {
pages.splice(len, 1)
})
}
function back(delta, animationType, animationDuration) {
const pages = getCurrentPages()
const len = pages.length
const currentPage = pages[len - 1]
if (delta > 1) {
// 中间页隐藏
pages.slice(len - delta, len - 1).reverse().forEach(deltaPage => {
deltaPage.$getAppWebview().close('none')
})
}
backWebview(currentPage, () => {
if (animationType) {
page.$getAppWebview().close(animationType, animationDuration || ANI_DURATION)
currentPage.$getAppWebview().close(animationType, animationDuration || ANI_DURATION)
} else {
page.$getAppWebview().close('auto')
currentPage.$getAppWebview().close('auto')
}
// 移除所有 page
pages.splice(len - delta, len)
setStatusBarStyle()
UniServiceJSBridge.emit('onAppRoute', {
type: 'navigateBack'
})
}
})
}
export function navigateBack({
delta,
animationType,
animationDuration
}) {
const pages = getCurrentPages()
const len = pages.length
uni.hideToast() // 后退时,关闭 toast,loading
pages[len - 1].$page.meta.isQuit ?
quit() :
back(delta, animationType, animationDuration)
}
import {
parseQuery
} from 'uni-shared'
import {
showWebview
} from './util'
import {
setStatusBarStyle
} from '../../bridge'
export function navigateTo ({
url,
animationType,
animationDuration
}) {
const path = url.split('?')[0]
const urls = url.split('?')
const path = urls[0]
const query = parseQuery(urls[1] || '')
UniServiceJSBridge.emit('onAppRoute', {
type: 'navigateTo',
......@@ -16,9 +27,12 @@ export function navigateTo ({
showWebview(
__registerPage({
path
path,
query
}),
animationType,
animationDuration
)
setStatusBarStyle()
}
......@@ -9,7 +9,7 @@ import {
TITLEBAR_HEIGHT
} from '../../constants'
import tabbar from '../../framework/tabbar'
import tabBar from '../../framework/tab-bar'
export function getSystemInfoSync () {
return callApiSync(getSystemInfo, Object.create(null), 'getSystemInfo', 'getSystemInfoSync')
......@@ -48,7 +48,7 @@ export function getSystemInfo () {
// TODO screenWidth,screenHeight
windowWidth: screenWidth,
windowHeight: Math.min(screenHeight - (titleNView ? (statusBarHeight + TITLEBAR_HEIGHT)
: 0) - (isTabBarPage() && tabbar.visible ? TABBAR_HEIGHT : 0), screenHeight),
: 0) - (isTabBarPage() && tabBar.visible ? TABBAR_HEIGHT : 0), screenHeight),
statusBarHeight,
language: plus.os.language,
system: plus.os.version,
......
......@@ -41,6 +41,7 @@ export * from './plugin/oauth'
export * from './plugin/payment'
export * from './plugin/push'
export * from './plugin/share'
export * from './plugin/event-bus'
export * from './ui/keyboard'
export * from './ui/navigation-bar'
......@@ -52,4 +53,4 @@ export {
}
from './ui/pull-down-refresh'
export * from './ui/tab-bar'
export * from './ui/tab-bar'
const Emitter = new Vue()
function apply (ctx, method, args) {
return ctx[method].apply(ctx, args)
}
export function $on () {
return apply(Emitter, '$on', [...arguments])
}
export function $off () {
return apply(Emitter, '$off', [...arguments])
}
export function $once () {
return apply(Emitter, '$once', [...arguments])
}
export function $emit () {
return apply(Emitter, '$emit', [...arguments])
}
......@@ -2,14 +2,14 @@ import {
isTabBarPage
} from '../util'
import tabbar from '../../framework/tabbar'
import tabBar from '../../framework/tab-bar'
export function setTabBarBadge ({
index,
text,
type
}) {
tabbar.setTabBarBadge(type, index, text)
tabBar.setTabBarBadge(type, index, text)
return {
errMsg: 'setTabBarBadge:ok'
}
......@@ -26,7 +26,7 @@ export function setTabBarItem ({
errMsg: 'setTabBarItem:fail not TabBar page'
}
}
tabbar.setTabBarItem(index, text, iconPath, selectedIconPath)
tabBar.setTabBarItem(index, text, iconPath, selectedIconPath)
return {
errMsg: 'setTabBarItem:ok'
}
......@@ -43,7 +43,7 @@ export function setTabBarStyle ({
errMsg: 'setTabBarStyle:fail not TabBar page'
}
}
tabbar.setTabBarStyle({
tabBar.setTabBarStyle({
color,
selectedColor,
backgroundColor,
......@@ -62,7 +62,7 @@ export function hideTabBar ({
errMsg: 'hideTabBar:fail not TabBar page'
}
}
tabbar.hideTabBar(animation)
tabBar.hideTabBar(animation)
return {
errMsg: 'hideTabBar:ok'
}
......@@ -76,7 +76,7 @@ export function showTabBar ({
errMsg: 'showTabBar:fail not TabBar page'
}
}
tabbar.showTabBar(animation)
tabBar.showTabBar(animation)
return {
errMsg: 'showTabBar:ok'
}
......
......@@ -13,4 +13,26 @@ export function requireNativePlugin (name) {
*/
export function publish (name, res) {
return UniServiceJSBridge.emit('api.' + name, res)
}
let lastStatusBarStyle
export function setStatusBarStyle (statusBarStyle) {
if (!statusBarStyle) {
const pages = getCurrentPages()
if (!pages.length) {
return
}
statusBarStyle = pages[pages.length - 1].$page.meta.statusBarStyle
if (!statusBarStyle || statusBarStyle === lastStatusBarStyle) {
return
}
}
if (process.env.NODE_ENV !== 'production') {
console.log(`[uni-app] setStatusBarStyle`, statusBarStyle)
}
lastStatusBarStyle = statusBarStyle
plus.navigator.setStatusBarStyle(statusBarStyle)
}
......@@ -2,6 +2,22 @@ import {
callAppHook
} from 'uni-core/service/plugins/util'
import initOn from 'uni-core/service/bridge/on'
import {
getCurrentPages
} from './page'
import {
registerPlusMessage
} from './plus-message'
import {
isTabBarPage
} from '../api/util'
import tabBar from './tab-bar'
let appCtx
const NETWORK_TYPES = [
......@@ -18,14 +34,11 @@ export function getApp () {
return appCtx
}
function initGlobalListeners ({
uni,
plus,
UniServiceJSBridge
}) {
function initGlobalListeners () {
const emit = UniServiceJSBridge.emit
plus.key.addEventListener('backbutton', () => {
// TODO uni?
uni.navigateBack({
from: 'backbutton'
})
......@@ -48,9 +61,7 @@ function initGlobalListeners ({
})
}
function initAppLaunch (appVm, {
__uniConfig
}) {
function initAppLaunch (appVm) {
const args = {
path: __uniConfig.entryPagePath,
query: {},
......@@ -61,14 +72,55 @@ function initAppLaunch (appVm, {
callAppHook(appVm, 'onShow', args)
}
export function registerApp (appVm, instanceContext) {
function initTabBar () {
if (!__uniConfig.tabBar || !__uniConfig.tabBar.list.length) {
return
}
const currentTab = isTabBarPage(__uniConfig.entryPagePath)
if (currentTab) {
// 取当前 tab 索引值
__uniConfig.tabBar.selected = __uniConfig.tabBar.list.indexOf(currentTab)
// 如果真实的首页与 condition 都是 tabbar,无需启用 realEntryPagePath 机制
if (__uniConfig.realEntryPagePath && isTabBarPage(__uniConfig.realEntryPagePath)) {
delete __uniConfig.realEntryPagePath
}
}
__uniConfig.__ready__ = true
const onLaunchWebviewReady = function onLaunchWebviewReady () {
const tabBarView = tabBar.init(__uniConfig.tabBar, (item) => {
uni.switchTab({
url: '/' + item.pagePath,
openType: 'switchTab',
from: 'tabbar'
})
})
tabBarView && plus.webview.getLaunchWebview().append(tabBarView)
}
if (plus.webview.getLaunchWebview()) {
onLaunchWebviewReady()
} else {
registerPlusMessage('UniWebviewReady-' + plus.runtime.appid, onLaunchWebviewReady, false)
}
}
export function registerApp (appVm) {
if (process.env.NODE_ENV !== 'production') {
console.log(`[uni-app] registerApp`)
}
appCtx = appVm
initAppLaunch(appVm, instanceContext)
initOn(UniServiceJSBridge.on, {
getApp,
getCurrentPages
})
initAppLaunch(appVm)
initGlobalListeners()
initGlobalListeners(instanceContext)
initTabBar()
}
import initOn from 'uni-core/service/bridge/on'
let bridge
export function initServiceJSBridge (Vue, instanceContext) {
if (bridge) {
return bridge
}
const Emitter = new Vue()
bridge = {
on: Emitter.$on.bind(Emitter),
off: Emitter.$off.bind(Emitter),
once: Emitter.$once.bind(Emitter),
emit: Emitter.$emit.bind(Emitter)
}
initOn(bridge.on, instanceContext)
return bridge
}
export const uniConfig = Object.create(null)
export const uniRoutes = []
function parseRoutes (config) {
uniRoutes.length = 0
__uniRoutes.length = 0
/* eslint-disable no-mixed-operators */
const tabBarList = (config.tabBar && config.tabBar.list || []).map(item => item.pagePath)
......@@ -10,7 +7,7 @@ function parseRoutes (config) {
const isTabBar = tabBarList.indexOf(pagePath) !== -1
const isQuit = isTabBar || (config.pages[0] === pagePath)
const isNVue = !!config.page[pagePath].nvue
uniRoutes.push({
__uniRoutes.push({
path: '/' + pagePath,
meta: {
isQuit,
......@@ -22,22 +19,20 @@ function parseRoutes (config) {
})
}
export function registerConfig (config, {
plus
}) {
Object.assign(uniConfig, config)
export function registerConfig (config) {
Object.assign(__uniConfig, config)
uniConfig.viewport = ''
uniConfig.defaultFontSize = ''
__uniConfig.viewport = ''
__uniConfig.defaultFontSize = ''
if (uniConfig.nvueCompiler === 'uni-app') {
uniConfig.viewport = plus.screen.resolutionWidth
uniConfig.defaultFontSize = uniConfig.viewport / 20
if (__uniConfig.nvueCompiler === 'uni-app') {
__uniConfig.viewport = plus.screen.resolutionWidth
__uniConfig.defaultFontSize = __uniConfig.viewport / 20
}
parseRoutes(uniConfig)
parseRoutes(__uniConfig)
if (process.env.NODE_ENV !== 'production') {
console.log(`[uni-app] registerConfig`, uniConfig)
console.log(`[uni-app] registerConfig`, __uniConfig)
}
}
import {
getApp,
registerApp
} from './app'
import {
registerPage,
getCurrentPages
} from './page'
import {
uniConfig,
uniRoutes,
registerConfig
} from './config'
import {
createUniInstance
} from './uni'
import {
initServiceJSBridge
} from './bridge'
let uni
export function createInstanceContext (instanceContext) {
const {
weex,
Vue,
WeexPlus
} = instanceContext
const plus = new WeexPlus(weex)
const UniServiceJSBridge = initServiceJSBridge(Vue, {
plus,
getApp,
getCurrentPages
})
function __registerPage (page) {
return registerPage(page, instanceContext)
}
if (!uni) {
uni = createUniInstance(
weex,
plus,
uniConfig,
uniRoutes,
__registerPage,
UniServiceJSBridge,
getApp,
getCurrentPages
)
}
return {
__uniConfig: uniConfig,
__uniRoutes: uniRoutes,
__registerConfig (config) {
return registerConfig(config, instanceContext)
},
__registerApp (appVm) {
return registerApp(appVm, instanceContext)
},
__registerPage,
plus,
uni,
getApp,
getCurrentPages,
UniServiceJSBridge
}
}
export function createHolder (webview, {
navigationBar
}, {
Vue
}) {
const navigationBarState = Vue.observable(navigationBar)
/* eslint-disable no-new */
new Vue({
created () {
this.$watch(() => navigationBarState.titleText, (val, oldVal) => {
webview.setStyle({
titleNView: {
titleText: val || ''
}
})
})
this.$watch(() => [navigationBarState.textColor, navigationBarState.backgroundColor], (val) => {
webview.setStyle({
titleNView: {
titleColor: val[0],
backgroundColor: val[1]
}
})
})
}
})
return {
navigationBar: navigationBarState
}
}
......@@ -25,33 +25,35 @@ export function getCurrentPages () {
*
*
*
*/
*/
/**
* 首页需要主动registerPage,二级页面路由跳转时registerPage
*/
export function registerPage ({
path,
query,
webview
}, instanceContext) {
const routeOptions = JSON.parse(JSON.stringify(instanceContext.__uniRoutes.find(route => route.path === path)))
}) {
const routeOptions = JSON.parse(JSON.stringify(__uniRoutes.find(route => route.path === path)))
if (!webview) {
webview = createWebview(path, instanceContext, routeOptions)
webview = createWebview(path, routeOptions)
}
if (process.env.NODE_ENV !== 'production') {
console.log(`[uni-app] registerPage`, path, webview.id)
}
initWebview(webview, instanceContext, webview.id === '1' && routeOptions)
initWebview(webview, webview.id === '1' && routeOptions)
const route = path.slice(1)
const route = path.slice(1)
webview.__uniapp_route = route
webview.__uniapp_route = route
pages.push({
route,
options: Object.assign({}, query || {}),
$getAppWebview () {
return webview
},
......
......@@ -59,18 +59,12 @@ let initView = function () {
viewStyles.bottom = 0
viewStyles.height += safeArea.bottom
}
if (process.env.NODE_ENV !== 'production') {
console.log(`UNIAPP[tabbar]:${JSON.stringify(viewStyles)}`)
}
view = new plus.nativeObj.View(TABBAR_VIEW_ID, viewStyles, getDraws())
view.interceptTouchEvent(true)
view.addEventListener('click', (e) => {
if (!__uniConfig.__ready__) { // 未 ready,不允许点击
if (process.env.NODE_ENV !== 'production') {
console.log(`UNIAPP[tabbar].prevent`)
}
return
}
const x = e.clientX
......
......@@ -7,10 +7,6 @@ import {
parseWebviewStyle
} from './parser/webview-style-parser'
import {
parseNavigationBar
} from './parser/navigation-bar-parser'
let id = 2
const WEBVIEW_LISTENERS = {
......@@ -20,45 +16,39 @@ const WEBVIEW_LISTENERS = {
'titleNViewSearchInputClicked': 'onNavigationBarSearchInputClicked'
}
export function createWebview (path, instanceContext, routeOptions) {
export function createWebview (path, routeOptions) {
const webviewId = id++
const webviewStyle = parseWebviewStyle(
webviewId,
path,
routeOptions,
instanceContext
routeOptions
)
if (process.env.NODE_ENV !== 'production') {
console.log(`[uni-app] createWebview`, webviewId, path, webviewStyle)
}
const webview = instanceContext.plus.webview.create('', String(webviewId), webviewStyle)
webview.$navigationBar = parseNavigationBar(webviewStyle)
const webview = plus.webview.create('', String(webviewId), webviewStyle)
return webview
}
export function initWebview (webview, instanceContext, routeOptions) {
export function initWebview (webview, routeOptions) {
if (isPlainObject(routeOptions)) {
const webviewStyle = parseWebviewStyle(
parseInt(webview.id),
'',
routeOptions,
instanceContext
routeOptions
)
if (process.env.NODE_ENV !== 'production') {
console.log(`[uni-app] updateWebview`, webviewStyle)
}
webview.$navigationBar = parseNavigationBar(webviewStyle)
webview.setStyle(webviewStyle)
}
const {
on,
emit
} = instanceContext.UniServiceJSBridge
} = UniServiceJSBridge
// TODO subNVues
Object.keys(WEBVIEW_LISTENERS).forEach(name => {
......
export function parsePullToRefresh (routeOptions, {
plus
}) {
export function parsePullToRefresh (routeOptions) {
const windowOptions = routeOptions.window
if (windowOptions.enablePullDownRefresh) {
......@@ -34,7 +32,7 @@ export function parsePullToRefresh (routeOptions, {
pullToRefreshStyles.snowColor = windowOptions.backgroundTextStyle
}
Object.assign(pullToRefreshStyles, windowOptions.pullToRefresh || {})
Object.assign(pullToRefreshStyles, windowOptions.pullToRefresh || {})
return pullToRefreshStyles
}
......
......@@ -24,6 +24,8 @@ export function parseTitleNView (routeOptions) {
titleColor: windowOptions.navigationBarTextStyle === 'black' ? '#000000' : '#ffffff'
}
routeOptions.meta.statusBarStyle = windowOptions.navigationBarTextStyle === 'black' ? 'dark' : 'light'
if (isPlainObject(titleNView)) {
return Object.assign(ret, titleNView)
}
......
......@@ -23,22 +23,18 @@ const WEBVIEW_STYLE_BLACKLIST = [
'pullToRefresh'
]
export function parseWebviewStyle (id, path, routeOptions = {}, instanceContext) {
const {
__uniConfig
} = instanceContext
export function parseWebviewStyle (id, path, routeOptions = {}) {
const webviewStyle = Object.create(null)
// 合并
const windowOptions = Object.assign(
routeOptions.window = Object.assign(
JSON.parse(JSON.stringify(__uniConfig.window || {})),
routeOptions.window || {}
)
Object.keys(windowOptions).forEach(name => {
Object.keys(routeOptions.window).forEach(name => {
if (WEBVIEW_STYLE_BLACKLIST.indexOf(name) === -1) {
webviewStyle[name] = windowOptions[name]
webviewStyle[name] = routeOptions.window[name]
}
})
......@@ -50,7 +46,7 @@ export function parseWebviewStyle (id, path, routeOptions = {}, instanceContext)
webviewStyle.titleNView = titleNView
}
const pullToRefresh = parsePullToRefresh(routeOptions, instanceContext)
const pullToRefresh = parsePullToRefresh(routeOptions)
if (pullToRefresh) {
if (pullToRefresh.style === 'circle') {
webviewStyle.bounce = 'none'
......
import {
getApp,
registerApp
} from './framework/app'
import {
registerPage,
getCurrentPages
} from './framework/page'
import {
registerConfig
} from './framework/config'
import {
uni
} from 'uni-core/service/uni'
import {
invokeCallbackHandler
} from 'uni-helpers/api'
UniServiceJSBridge.publishHandler = UniServiceJSBridge.emit // TODO
UniServiceJSBridge.invokeCallbackHandler = invokeCallbackHandler
export default {
__registerConfig: registerConfig,
__registerApp: registerApp,
__registerPage: registerPage,
uni,
getApp,
getCurrentPages
}
import {
invokeCallbackHandler
} from 'uni-helpers/api'
UniServiceJSBridge.publishHandler = UniServiceJSBridge.emit
UniServiceJSBridge.invokeCallbackHandler = invokeCallbackHandler
import './polyfill'
import apis from 'uni-helpers/apis'
import {
wrapper,
wrapperUnimplemented
} from 'uni-helpers/api'
import {
promisify
} from 'uni-helpers/promise'
import baseApi from 'uni-core/service/api'
import platformApi from 'uni-platform/service/api'
const api = Object.assign(Object.create(null), baseApi, platformApi)
const uni = Object.create(null)
apis.forEach(name => {
if (api[name]) {
uni[name] = promisify(name, wrapper(name, api[name]))
} else {
uni[name] = wrapperUnimplemented(name)
}
})
/**
* 请求任务类
*/
class RequestTask {
_xhr
constructor (xhr) {
this._xhr = xhr
}
abort () {
if (this._xhr) {
this._xhr.abort()
delete this._xhr
}
}
}
/**
* 拼接网址和参数
* @param {string} url 网址
* @param {any} data 参数
* @return {string}
*/
function setUrl (url, data) {
var str = url.split('#')
var hash = str[1] || ''
str = str[0].split('?')
var query = str[1] || ''
url = str[0]
var search = query.split('&').filter(item => item)
query = {}
search.forEach(item => {
item = item.split('=')
query[item[0]] = item[1]
})
for (var key in data) {
if (data.hasOwnProperty(key)) {
query[encodeURIComponent(key)] = encodeURIComponent(data[key])
}
}
query = Object.keys(query).map(item => `${item}=${query[item]}`).join('&')
return url + (query ? '?' + query : '') + (hash ? '#' + hash : '')
}
/**
* 解析响应头
* @param {string} headers
* @return {object}
*/
function parseHeaders (headers) {
var headersObject = {}
var headersArray = headers.split('\n')
headersArray.forEach(header => {
var find = header.match(/(\S+\s*):\s*(.*)/)
if (!find || find.length !== 3) {
return
}
var key = find[1]
var val = find[2]
headersObject[key] = val
})
return headersObject
}
/**
* 发起网络请求
* @param {object} param0
* @param {string} callbackId
* @return {RequestTask}
*/
export function request ({
url,
data,
header,
method,
dataType,
responseType
}, callbackId) {
const {
invokeCallbackHandler: invoke
} = UniServiceJSBridge
var body = null
var timeout = (__uniConfig.networkTimeout && __uniConfig.networkTimeout.request) || 60 * 1000
// 根据请求类型处理数据
var contentType
for (const key in header) {
if (header.hasOwnProperty(key)) {
if (key.toLowerCase() === 'content-type') {
contentType = header[key]
if (contentType.indexOf('application/json') === 0) {
contentType = 'json'
} else if (contentType.indexOf('application/x-www-form-urlencoded') === 0) {
contentType = 'urlencoded'
} else {
contentType = 'string'
}
break
}
}
}
if (method === 'GET') {
url = setUrl(url, data)
} else {
if (!contentType) {
/**
* 跨域时部分服务器OPTION响应头Access-Control-Allow-Headers未包含Content-Type会请求失败
*/
header['Content-Type'] = 'application/json'
contentType = 'json'
}
if (typeof data === 'string' || data instanceof ArrayBuffer) {
body = data
} else {
if (contentType === 'json') {
try {
body = JSON.stringify(data)
} catch (error) {
body = data.toString()
}
} else if (contentType === 'urlencoded') {
let bodyArray = []
for (let key in data) {
if (data.hasOwnProperty(key)) {
bodyArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
}
}
body = bodyArray.join('&')
} else {
body = data.toString()
}
}
}
var xhr = new XMLHttpRequest()
var requestTask = new RequestTask(xhr)
xhr.open(method, url)
for (var key in header) {
if (header.hasOwnProperty(key)) {
xhr.setRequestHeader(key, header[key])
}
}
var timer = setTimeout(function () {
xhr.onload = xhr.onabort = xhr.onerror = null
requestTask.abort()
invoke(callbackId, {
errMsg: 'request:fail timeout'
})
}, timeout)
xhr.responseType = responseType.toLowerCase()
xhr.onload = function () {
clearTimeout(timer)
let statusCode = xhr.status
let res = responseType === 'TEXT' ? xhr.responseText : xhr.response
if (responseType === 'TEXT' && dataType === 'JSON') {
try {
res = JSON.parse(res)
} catch (error) {
// 和微信一致解析失败不抛出错误
// invoke(callbackId, {
// errMsg: 'request:fail json parse error'
// })
// return
}
}
invoke(callbackId, {
data: res,
statusCode,
header: parseHeaders(xhr.getAllResponseHeaders()),
errMsg: 'request:ok'
})
}
xhr.onabort = function () {
clearTimeout(timer)
invoke(callbackId, {
errMsg: 'request:fail abort'
})
}
xhr.onerror = function () {
clearTimeout(timer)
invoke(callbackId, {
errMsg: 'request:fail'
})
}
xhr.send(body)
return requestTask
/**
* 请求任务类
*/
class RequestTask {
_xhr
constructor (xhr) {
this._xhr = xhr
}
abort () {
if (this._xhr) {
this._xhr.abort()
delete this._xhr
}
}
}
/**
* 解析响应头
* @param {string} headers
* @return {object}
*/
function parseHeaders (headers) {
var headersObject = {}
var headersArray = headers.split('\n')
headersArray.forEach(header => {
var find = header.match(/(\S+\s*):\s*(.*)/)
if (!find || find.length !== 3) {
return
}
var key = find[1]
var val = find[2]
headersObject[key] = val
})
return headersObject
}
/**
* 发起网络请求
* @param {object} param0
* @param {string} callbackId
* @return {RequestTask}
*/
export function request ({
url,
data,
header,
method,
dataType,
responseType
}, callbackId) {
const {
invokeCallbackHandler: invoke
} = UniServiceJSBridge
var body = null
var timeout = (__uniConfig.networkTimeout && __uniConfig.networkTimeout.request) || 60 * 1000
// 根据请求类型处理数据
var contentType
for (const key in header) {
if (header.hasOwnProperty(key)) {
if (key.toLowerCase() === 'content-type') {
contentType = header[key]
if (contentType.indexOf('application/json') === 0) {
contentType = 'json'
} else if (contentType.indexOf('application/x-www-form-urlencoded') === 0) {
contentType = 'urlencoded'
} else {
contentType = 'string'
}
break
}
}
}
if (method !== 'GET') {
if (!contentType) {
/**
* 跨域时部分服务器OPTION响应头Access-Control-Allow-Headers未包含Content-Type会请求失败
*/
header['Content-Type'] = 'application/json'
contentType = 'json'
}
if (typeof data === 'string' || data instanceof ArrayBuffer) {
body = data
} else {
if (contentType === 'json') {
try {
body = JSON.stringify(data)
} catch (error) {
body = data.toString()
}
} else if (contentType === 'urlencoded') {
let bodyArray = []
for (let key in data) {
if (data.hasOwnProperty(key)) {
bodyArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
}
}
body = bodyArray.join('&')
} else {
body = data.toString()
}
}
}
var xhr = new XMLHttpRequest()
var requestTask = new RequestTask(xhr)
xhr.open(method, url)
for (var key in header) {
if (header.hasOwnProperty(key)) {
xhr.setRequestHeader(key, header[key])
}
}
var timer = setTimeout(function () {
xhr.onload = xhr.onabort = xhr.onerror = null
requestTask.abort()
invoke(callbackId, {
errMsg: 'request:fail timeout'
})
}, timeout)
xhr.responseType = responseType.toLowerCase()
xhr.onload = function () {
clearTimeout(timer)
let statusCode = xhr.status
let res = responseType === 'TEXT' ? xhr.responseText : xhr.response
if (responseType === 'TEXT' && dataType === 'JSON') {
try {
res = JSON.parse(res)
} catch (error) {
// 和微信一致解析失败不抛出错误
// invoke(callbackId, {
// errMsg: 'request:fail json parse error'
// })
// return
}
}
invoke(callbackId, {
data: res,
statusCode,
header: parseHeaders(xhr.getAllResponseHeaders()),
errMsg: 'request:ok'
})
}
xhr.onabort = function () {
clearTimeout(timer)
invoke(callbackId, {
errMsg: 'request:fail abort'
})
}
xhr.onerror = function () {
clearTimeout(timer)
invoke(callbackId, {
errMsg: 'request:fail'
})
}
xhr.send(body)
return requestTask
}
......@@ -3,7 +3,7 @@ import initSubscribe from 'uni-core/service/bridge/subscribe'
import {
uni
} from './uni'
} from 'uni-core/service/uni'
import {
getApp,
......
export * from './env'
export * from './util'
export * from './color'
export * from './query'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册