提交 5b4abb66 编写于 作者: fxy060608's avatar fxy060608

feat(v3): navigator

上级 5c1d23b2
......@@ -32,7 +32,6 @@ if (process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_VIEW === 'true')
filename = 'view'
entry = './lib/' + process.env.UNI_PLATFORM + '/view.js'
}
service.run('build', {
name,
filename,
......@@ -40,7 +39,8 @@ service.run('build', {
target: 'lib',
formats: process.env.UNI_WATCH === 'true' ? 'umd' : 'umd-min',
entry,
clean: !process.env.UNI_VIEW
clean: !process.env.UNI_VIEW,
mode: process.env.NODE_ENV
}).then(function () {
if (process.env.UNI_UI !== 'true' && process.env.UNI_VIEW !== 'true') {
generateApiManifest(
......
......@@ -34,20 +34,24 @@ if (process.env.UNI_SERVICE === 'legacy') {
output.format = 'iife'
output.name = 'serviceContext'
output.banner =
`export function createServiceContext(Vue, weex, plus, __uniConfig, __uniRoutes, UniServiceJSBridge,instanceContext){
`export function createServiceContext(Vue, weex, plus, UniServiceJSBridge,instanceContext){
var localStorage = plus.storage
var setTimeout = instanceContext.setTimeout
var clearTimeout = instanceContext.clearTimeout
var setInterval = instanceContext.setInterval
var clearInterval = instanceContext.clearInterval
var clearInterval = instanceContext.clearInterval
var __uniConfig = instanceContext.__uniConfig
var __uniRoutes = instanceContext.__uniRoutes
`
output.footer =
`
var uni = serviceContext.uni
var getApp = serviceContext.getApp
var getCurrentPages = serviceContext.getCurrentPages
var __definePage = serviceContext.__definePage
var __registerPage = serviceContext.__registerPage
var __registerPage = serviceContext.__registerPage
return serviceContext \n}
`
......
......@@ -191,7 +191,8 @@ const third = [
'onPush',
'offPush',
'requireNativePlugin',
'upx2px'
'upx2px',
'registerPlus'
]
const apis = [
......
......@@ -4,11 +4,11 @@ import 'uni-core/view/index.css'
import {
definePage
} from 'uni-platform/view/framework/page'
} from 'uni-platform/page-factory'
import {
registerConfig
} from 'uni-platform/view/framework/config'
getCurrentPages
} from 'uni-platform/view/framework/page'
import ViewPlugin from 'uni-platform/view/framework/plugins/index'
......@@ -16,9 +16,10 @@ global.UniViewJSBridge = {
publishHandler: UniViewJSBridge.publishHandler,
subscribeHandler: UniViewJSBridge.subscribeHandler
}
global.getCurrentPages = getCurrentPages
global.__registerConfig = registerConfig
global.__registerPage = definePage
global.__definePage = definePage
global.Vue = Vue
......
......@@ -13,7 +13,7 @@
"build:app:v3": "npm run lint && npm run build:app:service && npm run dev:app:view",
"build:app:service": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.app.js",
"build:app:view": "cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js",
"dev:app:view": "cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js",
"dev:app:view": "cross-env NODE_ENV=development UNI_WATCH=true UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js",
"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",
......
......@@ -6719,7 +6719,7 @@ function updateExtras(oldVnode, vnode) {
if (attrs) {
for (var key$1 in attrs) {
key$1 !== '_i' && $s(id, key$1, attrs[key$1]);
key$1 !== '_i' && $s(id, 'a-' + key$1, attrs[key$1]);
}
}
// 存储事件标记
......
此差异已折叠。
......@@ -146,17 +146,18 @@ function isValidPage (page, root = '') {
// 存储 nvue 相关信息
pagePath = normalizePath(path.join(root, pagePath))
// if (process.env.UNI_USING_NVUE_COMPILER) {
process.UNI_NVUE_ENTRY[pagePath] = getNVueMainJsPath(pagePath)
// } else {
// process.UNI_NVUE_ENTRY[pagePath] = path.resolve(process.env.UNI_INPUT_DIR, pagePath + '.nvue') + '?entry'
// }
uniNVuePages.push({
'path': pagePath + '.html',
'style': page.style || {}
})
return false
if (process.env.UNI_USING_V3) { // 不移除
page.nvue = true
return true
} else {
uniNVuePages.push({
'path': pagePath + '.html',
'style': page.style || {}
})
return false
}
}
return true
......@@ -202,7 +203,7 @@ function parsePages (pagesJson, pageCallback, subPageCallback) {
}
}
function parseEntry (pagesJson) {
function parseEntry (pagesJson) {
process.UNI_ENTRY = {
'common/main': path.resolve(process.env.UNI_INPUT_DIR, getMainEntry())
}
......
......@@ -139,10 +139,17 @@ const PLATFORMS = {
})
}
let template = []
let view = []
if (process.env.UNI_USING_V3) {
view = getCopyOptions([
require.resolve('@dcloudio/uni-app-plus/dist/view.css'),
// TODO view.umd.min.js
require.resolve('@dcloudio/uni-app-plus/dist/view.umd.js')
])
template = getCopyOptions([path.resolve(__dirname, '../template')])
}
return [
...view,
...template,
...getStaticCopyOptions(assetsDir),
...wxcomponents,
......
此差异已折叠。
此差异已折叠。
......@@ -2,7 +2,7 @@ const compiler = require('../lib')
const res = compiler.compile(
`
<view>
<component v-for="component in components" :item="component.item" :is="component.mode"/>
<page-head v-if="a" v-for="item in items" :title="title"></page-head>
</view>
`, {
resourcePath: '/User/fxy/Documents/test.wxml',
......
const {
ID,
hasOwn
} = require('./util')
const tags = require('../../../uni-cli-shared/lib/tags')
const {
getTagName
} = require('../h5')
// 仅限 view 层
module.exports = function parseComponent (el) {
// TODO 需要把自定义组件的 attrs, props 全干掉
el.tag = getTagName(el.tag)
if (!hasOwn(tags, el.tag)) {
el.attrs = el.attrs.filter(attr => attr.name === ID)
}
}
const deprecated = {
events: {
'tap': 'click',
'longtap': 'longpress'
}
}
module.exports = function parseEvent (el) {
if (el.events) {
const {
events: eventsMap
} = deprecated
Object.keys(el.events).forEach(name => {
// 过时事件类型转换
if (eventsMap[name]) {
el.events[eventsMap[name]] = el.events[name]
delete el.events[name]
// warnLogs.add(`警告:事件${name}已过时,推荐使用${eventsMap[name]}代替`)
}
})
}
}
const {
tags,
hasOwn
} = require('@dcloudio/uni-cli-shared')
const {
ID,
hasOwn,
addAttr
} = require('./util')
module.exports = function preTransformNode (el, options) {
if (el.tag.indexOf('v-uni-') !== 0 && hasOwn(tags, el.tag)) {
el.tag = 'v-uni-' + el.tag
}
if (!hasOwn(options, 'nid')) {
options.nid = 0
}
......
......@@ -8,6 +8,7 @@ const {
} = require('./util')
const parseText = require('./text-parser')
const parseEvent = require('./event-parser')
const preTransformNode = require('./pre-transform-node')
......@@ -265,6 +266,8 @@ function processText (el) {
}
function postTransformNode (el) {
parseEvent(el)
removeStatic(el)
renameBinding(el)
......
const {
hasOwn
} = require('./util')
const tags = require('../../../uni-cli-shared/lib/tags')
// 仅限 view 层
module.exports = function parseTag (el) {
if (el.tag.indexOf('v-uni-') !== 0 && hasOwn(tags, el.tag)) {
el.tag = 'v-uni-' + el.tag
}
}
......@@ -114,5 +114,8 @@ module.exports = {
processForKey,
updateForEleId,
getBindingAttr,
getAndRemoveAttr
getAndRemoveAttr,
hasOwn: function (obj, key) {
return hasOwnProperty.call(obj, key)
}
}
......@@ -7,7 +7,10 @@ const {
processForKey
} = require('./util')
const parseTag = require('./tag-parser')
const parseText = require('./text-parser')
const parseEvent = require('./event-parser')
const parseComponent = require('./component-parser')
const preTransformNode = require('./pre-transform-node')
......@@ -134,6 +137,10 @@ function processText (el, genVar) {
}
function postTransformNode (el) {
parseComponent(el)
parseTag(el)
parseEvent(el)
updateForEleId(el)
const id = el.attrsMap[ID]
......
......@@ -36,12 +36,14 @@ const uniPath = process.env.UNI_USING_V8
const provide = {}
if (!process.env.UNI_USING_NATIVE) {
provide['uni'] = [path.resolve(__dirname, uniPath), 'default']
}
if (!process.env.UNI_USING_V3) { // v3 不需要
if (!process.env.UNI_USING_NATIVE) {
provide['uni'] = [path.resolve(__dirname, uniPath), 'default']
}
if (process.env.UNI_USING_V8) {
provide['plus'] = [path.resolve(__dirname, uniPath), 'weexPlus']
if (process.env.UNI_USING_V8) {
provide['plus'] = [path.resolve(__dirname, uniPath), 'weexPlus']
}
}
if (
......
......@@ -34,11 +34,13 @@ const v3 = {
// disable noEmitOnErrors
webpackConfig.optimization.noEmitOnErrors = false
if (isAppService) {
const externals = {}
if (isAppService) { // service 层需要编译时注入 vue 内核
webpackConfig.optimization.runtimeChunk = {
name: 'app-config'
}
} else if (isAppView) {
externals['vue'] = 'Vue'
webpackConfig.optimization.runtimeChunk = false
}
......@@ -63,7 +65,8 @@ const v3 = {
},
output: {
filename: '[name].js',
chunkFilename: '[id].js'
chunkFilename: '[id].js',
globalObject: 'this'
},
performance: {
hints: false
......@@ -83,6 +86,7 @@ const v3 = {
loader: isAppService ? 'wrap-loader' : path.resolve(__dirname,
'../../packages/webpack-uni-view-main-loader'),
options: {
compiler: getPlatformCompiler(),
before: [
beforeCode + statCode
]
......@@ -110,7 +114,7 @@ const v3 = {
webpackConfig.module
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.use('vue-loader')// service 层移除 style 节点,view 层返回固定 script
.loader(path.resolve(__dirname, '../../packages/vue-loader/lib'))
.tap(options => Object.assign(options, {
isAppView,
......
const postcss = require('postcss')
const selectorParser = require('postcss-selector-parser')
const valueParser = require('postcss-value-parser')
const {
getPlatformCssVars
} = require('@dcloudio/uni-cli-shared')
const CSS_TAGS = require('./tags')
const {
unit,
walk
} = valueParser
const defaultOpts = {
px: false
}
const cssVars = getPlatformCssVars()
const transformSelector = (complexSelector, transformer) => {
return selectorParser(transformer).processSync(complexSelector)
}
const parseWord = function (node, opts) {
const pair = unit(node.value)
if (pair) {
const num = Number(pair.number)
let u = pair.unit.toLowerCase()
if (u === 'px' && process.UNI_TRANSFORM_PX) { // TODO px 转换为 upx
u = 'upx'
}
if (process.env.UNI_PLATFORM === 'h5') {
if (u === 'upx' || u === 'rpx') {
node.value = `%?${num}?%`
}
} else {
if (u === 'upx') {
node.value = num + 'rpx'
if (process.env.UNI_USING_V3) {
module.exports = require('./index.v3.js')
} else {
const postcss = require('postcss')
const selectorParser = require('postcss-selector-parser')
const valueParser = require('postcss-value-parser')
const {
getPlatformCssVars
} = require('@dcloudio/uni-cli-shared')
const CSS_TAGS = require('./tags')
const {
unit,
walk
} = valueParser
const defaultOpts = {
px: false
}
const cssVars = getPlatformCssVars()
const transformSelector = (complexSelector, transformer) => {
return selectorParser(transformer).processSync(complexSelector)
}
const parseWord = function(node, opts) {
const pair = unit(node.value)
if (pair) {
const num = Number(pair.number)
let u = pair.unit.toLowerCase()
if (u === 'px' && process.UNI_TRANSFORM_PX) { // TODO px 转换为 upx
u = 'upx'
}
// fixed 百度目前1rpx会转换成小数点 vw,导致边框之类的显示有问题
if (process.env.UNI_PLATFORM === 'mp-baidu') {
if (num === 1 && (u === 'upx' || u === 'rpx')) {
node.value = '1px'
if (process.env.UNI_PLATFORM === 'h5') {
if (u === 'upx' || u === 'rpx') {
node.value = `%?${num}?%`
}
} else {
if (u === 'upx') {
node.value = num + 'rpx'
}
// fixed 百度目前1rpx会转换成小数点 vw,导致边框之类的显示有问题
if (process.env.UNI_PLATFORM === 'mp-baidu') {
if (num === 1 && (u === 'upx' || u === 'rpx')) {
node.value = '1px'
}
}
}
}
}
}
const isInsideKeyframes = function (rule) {
return (
rule.parent && rule.parent.type === 'atrule' && /^(-\w+-)?keyframes$/.test(rule.parent.name)
)
}
const tranformValue = function (decl, opts) {
return valueParser(decl.value)
.walk(node => {
if (node.type === 'word') {
parseWord(node, opts)
} else if (node.type === 'function') {
if (node.value === 'url') {
return false
}
if (node.value === 'var') {
let cssVarValue = false
walk(node.nodes, n => {
if (n.type === 'word') {
if (cssVars.hasOwnProperty(n.value)) { // 目前仅考虑 nodes 长度为0
cssVarValue = cssVars[n.value]
const isInsideKeyframes = function(rule) {
return (
rule.parent && rule.parent.type === 'atrule' && /^(-\w+-)?keyframes$/.test(rule.parent.name)
)
}
const tranformValue = function(decl, opts) {
return valueParser(decl.value)
.walk(node => {
if (node.type === 'word') {
parseWord(node, opts)
} else if (node.type === 'function') {
if (node.value === 'url') {
return false
}
if (node.value === 'var') {
let cssVarValue = false
walk(node.nodes, n => {
if (n.type === 'word') {
if (cssVars.hasOwnProperty(n.value)) { // 目前仅考虑 nodes 长度为0
cssVarValue = cssVars[n.value]
}
}
})
if (cssVarValue !== false) {
node.type = 'word'
node.value = cssVarValue
delete node.before
delete node.after
delete node.nodes
}
})
if (cssVarValue !== false) {
node.type = 'word'
node.value = cssVarValue
delete node.before
delete node.after
delete node.nodes
return false
} else {
walk(node.nodes, n => {
if (n.type === 'word') {
parseWord(n, opts)
}
})
}
return false
} else {
walk(node.nodes, n => {
if (n.type === 'word') {
parseWord(n, opts)
}
})
}
}
})
.toString()
}
const TAGS = [
'ad',
'audio',
'button',
'camera',
'canvas',
'checkbox',
'checkbox-group',
'cover-image',
'cover-view',
'form',
'functional-page-navigator',
'icon',
'image',
'input',
'label',
'live-player',
'live-pusher',
'map',
'movable-area',
'movable-view',
'navigator',
'official-account',
'open-data',
'picker',
'picker-view',
'picker-view-column',
'progress',
'radio',
'radio-group',
'rich-text',
'scroll-view',
'slider',
'swiper',
'swiper-item',
'switch',
'text',
'textarea',
'video',
'view',
'web-view'
]
const BG_PROPS = [
'background',
'background-clip',
'background-color',
'background-image',
'background-origin',
'background-position',
'background-repeat',
'background-size',
'background-attachment'
]
/**
* 转换 upx
* 转换 px
*/
module.exports = postcss.plugin('postcss-uniapp-plugin', function (opts) {
opts = {
...defaultOpts,
...opts
})
.toString()
}
return function (root, result) {
if (process.env.UNI_PLATFORM === 'h5') {
// Transform CSS AST here
const bgDecls = []
root.walkRules(rule => {
let hasPage = false
// Transform each rule here
if (!isInsideKeyframes(rule)) {
// rule.selectors == comma seperated selectors
// a, b.c {} => ["a", "b.c"]
rule.selectors = rule.selectors.map(complexSelector =>
// complexSelector => simpleSelectors
// "a.b#c" => ["a", ".b", "#c"]
transformSelector(complexSelector, simpleSelectors =>
// only process type selector, leave alone class & id selectors
simpleSelectors.walkTags(tag => {
if (tag.value === 'page') {
tag.value = 'uni-page-body'
hasPage = true
} else if (~TAGS.indexOf(tag.value) && tag.value.substring(
0, 4) !== 'uni-') {
tag.value = 'uni-' + tag.value
}
})
const TAGS = [
'ad',
'audio',
'button',
'camera',
'canvas',
'checkbox',
'checkbox-group',
'cover-image',
'cover-view',
'form',
'functional-page-navigator',
'icon',
'image',
'input',
'label',
'live-player',
'live-pusher',
'map',
'movable-area',
'movable-view',
'navigator',
'official-account',
'open-data',
'picker',
'picker-view',
'picker-view-column',
'progress',
'radio',
'radio-group',
'rich-text',
'scroll-view',
'slider',
'swiper',
'swiper-item',
'switch',
'text',
'textarea',
'video',
'view',
'web-view'
]
const BG_PROPS = [
'background',
'background-clip',
'background-color',
'background-image',
'background-origin',
'background-position',
'background-repeat',
'background-size',
'background-attachment'
]
/**
* 转换 upx
* 转换 px
*/
module.exports = postcss.plugin('postcss-uniapp-plugin', function(opts) {
opts = {
...defaultOpts,
...opts
}
return function(root, result) {
if (process.env.UNI_PLATFORM === 'h5') {
// Transform CSS AST here
const bgDecls = []
root.walkRules(rule => {
let hasPage = false
// Transform each rule here
if (!isInsideKeyframes(rule)) {
// rule.selectors == comma seperated selectors
// a, b.c {} => ["a", "b.c"]
rule.selectors = rule.selectors.map(complexSelector =>
// complexSelector => simpleSelectors
// "a.b#c" => ["a", ".b", "#c"]
transformSelector(complexSelector, simpleSelectors =>
// only process type selector, leave alone class & id selectors
simpleSelectors.walkTags(tag => {
if (tag.value === 'page') {
tag.value = 'uni-page-body'
hasPage = true
} else if (~TAGS.indexOf(tag.value) && tag.value.substring(
0, 4) !== 'uni-') {
tag.value = 'uni-' + tag.value
}
})
)
)
)
}
// handle upx unit
rule.walkDecls(decl => {
if (hasPage) {
if (BG_PROPS.indexOf(decl.prop) !== -1) {
bgDecls.push(decl.clone())
}
}
// Transform each property declaration here
decl.value = tranformValue(decl, opts)
// handle upx unit
rule.walkDecls(decl => {
if (hasPage) {
if (BG_PROPS.indexOf(decl.prop) !== -1) {
bgDecls.push(decl.clone())
}
}
// Transform each property declaration here
decl.value = tranformValue(decl, opts)
})
})
})
if (bgDecls.length) {
const rule = postcss.rule({
selector: 'body.?%PAGE?%'
})
bgDecls.forEach(decl => rule.append(decl))
root.append(rule)
}
} else {
root.walkRules(rule => {
const selectors = transformSelector(rule.selectors.join(','), function (selectors) {
selectors.walkUniversals(node => {
node.parent.remove()
if (bgDecls.length) {
const rule = postcss.rule({
selector: 'body.?%PAGE?%'
})
})
if (!selectors) {
return rule.remove()
bgDecls.forEach(decl => rule.append(decl))
root.append(rule)
}
rule.selectors = selectors.split(',')
// handle upx unit
rule.walkDecls(decl => {
const raws = decl.raws
if (raws) {
if (raws.before && raws.before.indexOf(';') !== -1) {
raws.before = raws.before.replace(/;/g, '')
}
if (raws.after && raws.after.indexOf(';') !== -1) {
raws.after = raws.after.replace(/;/g, '')
}
} else {
root.walkRules(rule => {
const selectors = transformSelector(rule.selectors.join(','), function(selectors) {
selectors.walkUniversals(node => {
node.parent.remove()
})
})
if (!selectors) {
return rule.remove()
}
// Transform each property declaration here
decl.value = tranformValue(decl, opts)
})
rule.selectors = rule.selectors.map(complexSelector => {
return transformSelector(complexSelector, simpleSelectors => {
return simpleSelectors.walkTags(tag => {
const k = tag.value
const v = CSS_TAGS[k]
if (v) {
tag.value = v === 'r'
? `._${k}` : v
rule.selectors = selectors.split(',')
// handle upx unit
rule.walkDecls(decl => {
const raws = decl.raws
if (raws) {
if (raws.before && raws.before.indexOf(';') !== -1) {
raws.before = raws.before.replace(/;/g, '')
}
if (raws.after && raws.after.indexOf(';') !== -1) {
raws.after = raws.after.replace(/;/g, '')
}
}
// Transform each property declaration here
decl.value = tranformValue(decl, opts)
})
rule.selectors = rule.selectors.map(complexSelector => {
return transformSelector(complexSelector, simpleSelectors => {
return simpleSelectors.walkTags(tag => {
const k = tag.value
const v = CSS_TAGS[k]
if (v) {
tag.value = v === 'r' ?
`._${k}` : v
}
})
})
})
})
})
}
}
}
})
})
}
const postcss = require('postcss')
const selectorParser = require('postcss-selector-parser')
const TAGS = Object.keys(require('@dcloudio/uni-cli-shared').tags)
const transformSelector = (complexSelector, transformer) => {
return selectorParser(transformer).processSync(complexSelector)
}
const isInsideKeyframes = function(rule) {
return (
rule.parent && rule.parent.type === 'atrule' && /^(-\w+-)?keyframes$/.test(rule.parent.name)
)
}
module.exports = postcss.plugin('postcss-uniapp-plugin', function(opts) {
return function(root, result) {
root.walkRules(rule => {
// Transform each rule here
if (!isInsideKeyframes(rule)) {
// rule.selectors == comma seperated selectors
// a, b.c {} => ["a", "b.c"]
rule.selectors = rule.selectors.map(complexSelector =>
// complexSelector => simpleSelectors
// "a.b#c" => ["a", ".b", "#c"]
transformSelector(complexSelector, simpleSelectors =>
// only process type selector, leave alone class & id selectors
simpleSelectors.walkTags(tag => {
if (tag.value === 'page') {
tag.value = 'body'
} else if (~TAGS.indexOf(tag.value) && tag.value.substring(
0, 4) !== 'uni-') {
tag.value = 'uni-' + tag.value
}
})
)
)
}
})
}
})
const fs = require('fs')
const path = require('path')
const hash = require('hash-sum')
const loaderUtils = require('loader-utils')
const parser = require('@babel/parser')
const {
parse
} = require(require.resolve('@vue/component-compiler-utils', {
paths: [require.resolve('vue-loader')]
})) // 确保使用的与 vue-loader 一致
const traverse = require('@dcloudio/webpack-uni-mp-loader/lib/babel/global-component-traverse')
const genStylesCode = require('../vue-loader/lib/codegen/styleInjection')
function parseComponents(content) {
const {
state: {
components
}
} = traverse(parser.parse(content, {
sourceType: 'module',
plugins: [
'typescript',
['decorators', {
decoratorsBeforeExport: true
}],
'classProperties'
]
}), {
components: []
})
return components
}
function getDefineComponents(components) {
return components.map(({
name,
source
}) => `Vue.component('${name}',require('${source}').default)`)
}
const appVueFilePath = path.resolve(process.env.UNI_INPUT_DIR, 'app.vue')
function getStylesCode(loaderContext) {
if (!fs.existsSync(appVueFilePath)) {
return
}
const source = fs.readFileSync(appVueFilePath, 'utf8')
const {
minimize,
sourceMap,
rootContext,
resourcePath,
resourceQuery
} = loaderContext
const options = loaderUtils.getOptions(loaderContext) || {}
const filename = path.basename(resourcePath)
const context = rootContext || process.cwd()
const sourceRoot = path.dirname(path.relative(context, resourcePath))
const descriptor = parse({
source,
compiler: options.compiler,
filename,
sourceRoot,
needMap: sourceMap
})
// styles
let stylesCode = ``
if (descriptor.styles.length) {
const isServer = false
const isShadow = false
const isProduction = options.productionMode || minimize || process.env.NODE_ENV === 'production'
const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r)
// module id for scoped CSS & hot-reload
const rawShortFilePath = path
.relative(context, resourcePath)
.replace(/^(\.\.[/\\])+/, '')
const shortFilePath = rawShortFilePath.replace(/\\/g, '/') + resourceQuery
const needsHotReload = false
const id = hash(
isProduction ?
(shortFilePath + '\n' + source) :
shortFilePath
)
stylesCode = genStylesCode(
loaderContext,
descriptor.styles,
id,
resourcePath,
stringifyRequest,
needsHotReload,
isServer || isShadow // needs explicit injection?
)
}
return stylesCode.replace(/main\.js/g,'App.vue')
}
module.exports = function(source, map) {
return `import 'uni-pages';
// 解析自定义组件,及 App 样式
return `import 'uni-pages'
${getStylesCode(this)}
${getDefineComponents(parseComponents(source)).join('\n')}
UniViewJSBridge.publishHandler('webviewReady')
`
}
......@@ -73,7 +73,7 @@ module.exports = function (content) {
let appConfigContent = ''
jsonFiles.forEach(jsonFile => {
if (jsonFile) {
if (jsonFile.name === 'app-config.js') {
if (jsonFile.name === 'define-pages.js') {
appConfigContent = jsonFile.content
} else {
this.emitFile(jsonFile.name, jsonFile.content)
......
function parseRoutes (config) {
const __uniRoutes = []
/* eslint-disable no-mixed-operators */
const tabBarList = (config.tabBar && config.tabBar.list || []).map(item => item.pagePath)
Object.keys(config.page).forEach(function (pagePath) {
const isTabBar = tabBarList.indexOf(pagePath) !== -1
const isQuit = isTabBar || (config.pages[0] === pagePath)
const isNVue = !!config.page[pagePath].nvue
const route = {
path: '/' + pagePath,
meta: {},
window: config.page[pagePath].window || {}
}
if (isQuit) {
route.meta.isQuit = true
}
if (isNVue) {
route.meta.isNVue = true
}
if (isTabBar) {
route.meta.isTabBar = true
}
__uniRoutes.push(route)
})
return __uniRoutes
}
module.exports = function definePages (appJson) {
const __uniRoutes = parseRoutes(appJson)
delete appJson.page
delete appJson.usingComponents
delete appJson.nvueCompiler
delete appJson.renderer
return {
name: 'app-config-service.js',
content: `
var isReady=false;var onReadyCallbacks=[];
var __uniConfig = ${JSON.stringify(appJson, null)};
var __uniRoutes = ${JSON.stringify(__uniRoutes)};
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register('uni-app-config', {create(id, env, config) {if(!__uniConfig.viewport){Object.assign(__uniConfig,{"viewport": env.weex.config.env.deviceWidth,"defaultFontSize": env.weex.config.env.deviceWidth / 20})}return {instance: {__uniConfig: __uniConfig,__uniRoutes: __uniRoutes}}}});
`
}
}
function generatePageCode (pages) {
return pages.map(pagePath => {
return `__registerPage('${pagePath}',function(){
const cacheKey = '${pagePath}-VueComponent'
if(!this[cacheKey]){
this[cacheKey] = Vue.extend(require('${pagePath}.vue').default)
}
return this[cacheKey]
})`
}).join('\n')
}
module.exports = function parseConfig (appJson) {
return {
name: 'app-config.js',
content: `
import Vue from 'vue'
__registerConfig(${JSON.stringify(appJson)},Vue)
${generatePageCode(appJson.pages)}
`
}
}
function generatePageCode (pages, pageOptions) {
return pages.map(pagePath => {
if (pageOptions[pagePath].nvue) {
return ''
}
return `__definePage('${pagePath}',function(){return Vue.extend(require('${pagePath}.vue').default)})`
}).join('\n')
}
module.exports = function definePages (appJson) {
return {
name: 'define-pages.js',
content: `
uni.registerPlus && uni.registerPlus(typeof plus !== 'undefined' && plus)
${generatePageCode(appJson.pages, appJson.page)}
`
}
}
......@@ -13,7 +13,8 @@ const {
parseStyle
} = require('../../util')
const parseV3Config = require('./config-parser')
const definePages = require('./define-pages')
const appConfigService = require('./app-config-service')
function parseConfig (appJson) {
return {
......@@ -316,11 +317,17 @@ module.exports = function (pagesJson, userManifestJson) {
}
if (!Object.keys(appJson.nvue.pages).find(path => {
const subNVues = appJson.nvue.pages[path].window.subNVues || []
return path.replace(/\.html$/, '.nvue') === key || subNVues.find(({ path }) => path === key.replace(/\.nvue$/, ''))
}) && !pagesJson.pages.find(({ style = {} }) => {
return path.replace(/\.html$/, '.nvue') === key || subNVues.find(({
path
}) => path === key.replace(/\.nvue$/, ''))
}) && !pagesJson.pages.find(({
style = {}
}) => {
style = Object.assign(style, style['app-plus'])
const subNVues = style.subNVues || []
return subNVues.find(({ path }) => path === key.replace(/\.nvue$/, ''))
return subNVues.find(({
path
}) => path === key.replace(/\.nvue$/, ''))
})) {
throw new Error(`原生混淆页面未在项目内使用,错误的页面路径:${key}`)
}
......@@ -404,7 +411,8 @@ module.exports = function (pagesJson, userManifestJson) {
manifestJson.plus.launchwebview.id = '2'
} else {
// 首页是 tabBar 页面
const item = tabBar.list.find(page => page.pagePath === (process.env.UNI_USING_NATIVE ? appJson.entryPagePath : entryPagePath))
const item = tabBar.list.find(page => page.pagePath === (process.env.UNI_USING_NATIVE ? appJson.entryPagePath
: entryPagePath))
if (item) {
tabBar.child = ['lauchwebview']
tabBar.selected = tabBar.list.indexOf(item)
......@@ -432,31 +440,54 @@ module.exports = function (pagesJson, userManifestJson) {
delete appJson.subPackages
// TODO 处理纯原生
if (process.env.UNI_USING_NATIVE) {
manifest.name = 'manifest.json'
manifest.content = JSON.stringify(manifest.content)
return [manifest, parseConfig(appJson)]
}
if (process.env.UNI_USING_V3) {
appJson.entryPagePath = appJson.pages[0]
if (process.env.UNI_USING_V3) { // v3
appJson.entryPagePath = appJson.pages[0]
// timeout
normalizeNetworkTimeout(appJson)
appJson.page = Object.create(null)
const addPage = function (pagePath, windowOptions) {
const addPage = function (pagePath, windowOptions, nvue) {
delete windowOptions.usingComponents
appJson.page[pagePath] = {
window: windowOptions
window: windowOptions,
nvue
}
}
parsePages(pagesJson, function (page) {
addPage(page.path, parseStyle(page.style))
addPage(page.path, parseStyle(page.style), !!page.nvue)
}, function (root, page) {
addPage(normalizePath(path.join(root, page.path)), parseStyle(page.style, root))
addPage(normalizePath(path.join(root, page.path)), parseStyle(page.style, root), !!page.nvue)
})
// nvue 权限
manifestJson.permissions.UniNView = {
'description': 'UniNView原生渲染'
}
// TODO 需要考虑 condition
manifestJson.plus.launchwebview.id = '1' // 首页 id 固定 为 1
if (appJson.page[appJson.entryPagePath].nvue) { // 首页是 nvue
manifestJson.launch_path = '' // 首页地址为空
manifestJson.plus.launchwebview.uniNView = {
path: appJson.entryPagePath
}
if (manifestJson.plus.tabBar) {
manifestJson.plus.tabBar.child = ['lauchwebview']
}
} else {
manifestJson.plus.launch_path = '__uniappview.html' // 首页地址固定
}
manifest.name = 'manifest.json'
manifest.content = JSON.stringify(manifest.content)
return [manifest, parseV3Config(appJson)]
delete appJson.nvue
return [manifest, definePages(appJson), appConfigService(appJson)]
}
return [app, manifest]
}
}
......@@ -21,6 +21,9 @@ export function unsubscribe (event, callback) {
}
export function subscribeHandler (event, args, pageId) {
if (process.env.NODE_ENV !== 'production') {
console.log(`[subscribeHandler][${Date.now()}]:`, event, args, pageId)
}
return emit('view.' + event, args, pageId)
}
......
......@@ -18,6 +18,9 @@ export function unsubscribe (event, callback) {
}
export function subscribeHandler (event, args, pageId) {
if (process.env.NODE_ENV !== 'production') {
console.log(`[subscribeHandler][${Date.now()}]:`, event, args, pageId)
}
emit('service.' + event, args, pageId)
}
......
......@@ -76,7 +76,7 @@ export function processEvent (name, $event = {}, detail = {}, target = {}, curre
}
// fixed mp-vue
return wrapperMPEvent({
const ret = wrapperMPEvent({
type: detail.type || name,
timeStamp: $event.timeStamp || 0,
detail: detail,
......@@ -84,10 +84,20 @@ export function processEvent (name, $event = {}, detail = {}, target = {}, curre
currentTarget: processTarget(currentTarget),
// 只处理系统事件
touches: ($event instanceof Event || $event instanceof CustomEvent) ? processTouches($event.touches) : $event.touches,
changedTouches: ($event instanceof Event || $event instanceof CustomEvent) ? processTouches($event.changedTouches) : $event.changedTouches,
preventDefault () { },
stopPropagation () { }
changedTouches: ($event instanceof Event || $event instanceof CustomEvent) ? processTouches($event.changedTouches)
: $event.changedTouches,
preventDefault () {},
stopPropagation () {}
})
if (__PLATFORM__ === 'app-plus') {
const nid = currentTarget.getAttribute('_i')
ret.options = {
nid
}
}
return ret
}
const LONGPRESS_TIMEOUT = 350
......@@ -124,14 +134,14 @@ function touchstart (evt) {
startPageX = pageX
startPageY = pageY
longPressTimer = setTimeout(function () {
longPressTimer = setTimeout(function () {
let customEvent = new CustomEvent('longpress', {
bubbles: true,
cancelable: true,
target: evt.target,
currentTarget: evt.currentTarget
})
customEvent.touches = evt.touches
})
customEvent.touches = evt.touches
customEvent.changedTouches = evt.changedTouches
evt.target.dispatchEvent(customEvent)
}, LONGPRESS_TIMEOUT)
......@@ -163,4 +173,4 @@ export function initEvents () {
window.addEventListener('touchmove', touchmove, passiveOptions)
window.addEventListener('touchend', clearLongPressTimer, passiveOptions)
window.addEventListener('touchcancel', clearLongPressTimer, passiveOptions)
}
}
export {
registerPage
}
from '../../app-plus/service/framework/page'
import {
cached
} from 'uni-shared'
const pageFactory = Object.create(null)
export function definePage (name, createPageVueComponent) {
pageFactory[name] = createPageVueComponent
}
export const getPageVueComponent = cached(function (pagePath) {
return pageFactory[pagePath]()
})
export function createPage (pagePath, pageId) {
if (!pageFactory[pagePath]) {
console.error(`${pagePath} not found`)
}
let startTime = Date.now()
const pageVm = new (getPageVueComponent(pagePath))({
mpType: 'page',
pageId,
pagePath
})
if (process.env.NODE_ENV !== 'production') {
console.log(`new ${pagePath}`, Date.now() - startTime)
}
return pageVm
}
......@@ -41,7 +41,8 @@ export * from './plugin/oauth'
export * from './plugin/payment'
export * from './plugin/push'
export * from './plugin/require-native-plugin'
export * from './plugin/share'
export * from './plugin/share'
export * from './plugin/register-plus'
export * from './route/navigate-back'
export * from './route/navigate-to'
......
export function registerPlus (newPlus) {
// 确保 plus 是 app-service 中的
if (plus !== newPlus) {
if (process.env.NODE_ENV !== 'production') {
console.log(`[registerPlus][${Date.now()}]`)
}
plus = newPlus
}
}
import {
ANI_CLOSE,
ANI_DURATION
} from './util'
} from '../../constants'
import {
setStatusBarStyle
......@@ -102,4 +102,4 @@ export function navigateBack ({
return {
errMsg: 'navigateBack:ok'
}
}
}
......@@ -17,20 +17,20 @@ import {
import tabBar from '../../../../app-plus/service/framework/tab-bar'
export function reLaunch ({
url
}, callbackId) {
const urls = url.split('?')
const path = urls[0]
const query = parseQuery(urls[1] || '')
import {
navigate
} from '../../framework/navigator'
function _reLaunch ({
path,
query
}, callbackId) {
const pages = getCurrentPages(true).slice(0)
const routeOptions = __uniRoutes.find(route => route.path === path)
if (routeOptions.meta.isTabBar) {
tabBar.switchTab(url)
tabBar.switchTab(path)
}
showWebview(
......@@ -55,3 +55,17 @@ export function reLaunch ({
setStatusBarStyle()
}
export function reLaunch ({
url
}, callbackId) {
const urls = url.split('?')
const path = urls[0]
const query = parseQuery(urls[1] || '')
navigate(path, function () {
_reLaunch({
path,
query
}, callbackId)
})
}
......@@ -15,14 +15,14 @@ import {
registerPage
} from '../../framework/page'
export function redirectTo ({
url
}, callbackId) {
const urls = url.split('?')
const path = urls[0]
const query = parseQuery(urls[1] || '')
import {
navigate
} from '../../framework/navigator'
function _redirectTo ({
path,
query
}, callbackId) {
const pages = getCurrentPages()
const lastPage = pages[pages.length - 1]
......@@ -46,3 +46,16 @@ export function redirectTo ({
setStatusBarStyle()
}
export function redirectTo ({
url
}, callbackId) {
const urls = url.split('?')
const path = urls[0]
const query = parseQuery(urls[1] || '')
navigate(path, function () {
_redirectTo({
path,
query
}, callbackId)
})
}
import {
ANI_CLOSE,
ANI_DURATION,
ANI_DURATION
} from '../../constants'
import {
showWebview
} from './util'
......@@ -17,7 +20,7 @@ import {
navigate
} from '../../framework/navigator'
import tabBar from '../../../../app-plus/service/framework/tab-bar'
import tabBar from '../../framework/tab-bar'
function _switchTab ({
path,
......
import {
navigateStack
ANI_SHOW,
ANI_DURATION
} from '../../constants'
import {
navigateFinish
} from '../../framework/navigator'
export const ANI_DURATION = 300
const ANI_SHOW = 'pop-in'
export const ANI_CLOSE = 'pop-out'
export function showWebview (webview, animationType, animationDuration, showCallback, delay) {
if (typeof delay === 'undefined') {
delay = webview.nvue ? 0 : 100
}
if (typeof animationDuration === 'undefined') {
animationDuration = ANI_DURATION
} else {
animationDuration = parseInt(animationDuration)
}
export function showWebview (webview, animationType, animationDuration, showCallback, delay = 50) {
animationDuration = typeof animationDuration === 'undefined' ? ANI_DURATION : parseInt(animationDuration)
if (process.env.NODE_ENV !== 'production') {
console.log(`[show][${Date.now()}]`, delay)
}
setTimeout(() => {
webview.show(
animationType || ANI_SHOW,
animationDuration || ANI_DURATION,
() => {
if (process.env.NODE_ENV !== 'production') {
console.log(`[show.callback][${Date.now()}]`)
}
showCallback && showCallback()
navigateStack(webview)
navigateFinish(webview)
}
)
}, delay)
......
export const ANI_SHOW = 'pop-in'
export const ANI_DURATION = 300
export const TITLEBAR_HEIGHT = 44
export const ANI_SHOW = plus.os.name === 'Android' && parseInt(plus.os.version) < 6 ? 'slide-in-right' : 'pop-in'
export const ANI_DURATION = 300
export const VIEW_WEBVIEW_PATH = '__uniappview.html'
export const ANI_CLOSE = 'pop-out'
export const TITLEBAR_HEIGHT = 44
export const VIEW_WEBVIEW_PATH = '_www/__uniappview.html'
......@@ -102,8 +102,6 @@ function initTabBar () {
__uniConfig.tabBar.selected = selected
}
__uniConfig.__ready__ = true
tabBar.init(__uniConfig.tabBar, (item, index) => {
uni.switchTab({
url: '/' + item.pagePath,
......@@ -142,5 +140,7 @@ export function registerApp (appVm) {
initAppLaunch(appVm)
__uniConfig.ready = true
process.env.NODE_ENV !== 'production' && perf('registerApp')
}
import plugin from './plugins/index'
function parseRoutes (config) {
__uniRoutes.length = 0
/* eslint-disable no-mixed-operators */
......@@ -21,10 +19,7 @@ function parseRoutes (config) {
})
}
export function registerConfig (config, Vue) {
if (__PLATFORM__ === 'app-plus') {
Vue.use(plugin)
}
export function registerConfig (config, Vue) {
Object.assign(__uniConfig, config)
__uniConfig.viewport = ''
......
......@@ -4,31 +4,62 @@ import {
registerWebviewReady
} from './webview'
export const navigatorStack = []
let todoNavigator = false
export function navigate (path, callback) {
let isReady = true
if (navigatorStack.length) { // 已存在路由跳转
isReady = false
} else {
callback.nvue = __uniConfig.page[path.slice(1)].nvue // 设置 nvue 标记
// 非 nvue 且 preloadWebview 未准备好
if (!callback.nvue && (!preloadWebview || !preloadWebview.loaded)) {
isReady = false
if (__PLATFORM__ === 'app-plus') {
if (todoNavigator) {
return console.error(`已存在待跳转页面${todoNavigator.path},请不要连续多次跳转页面`)
}
// 未创建 preloadWebview 或 preloadWebview 已被使用
const waitPreloadWebview = !preloadWebview || (preloadWebview && preloadWebview.__uniapp_route)
// 已创建未 loaded
const waitPreloadWebviewReady = preloadWebview && !preloadWebview.loaded
if (waitPreloadWebview || waitPreloadWebviewReady) {
todoNavigator = {
path: path,
nvue: __uniRoutes.find(route => route.path === path).meta.isNVue,
navigate: callback
}
if (process.env.NODE_ENV !== 'production') {
console.log(`todoNavigator:${todoNavigator.path} ${waitPreloadWebview ? 'waitForCreate' : 'waitForReady'}`)
}
} else {
callback()
}
if (waitPreloadWebviewReady) {
registerWebviewReady(preloadWebview.id, todoNavigate)
}
}
isReady ? callback() : navigatorStack.push(callback)
}
export function navigateStack (webview) {
if (!navigatorStack.length) {
return (!webview.nvue && createPreloadWebview())
function todoNavigate () {
if (!todoNavigator) {
return
}
const {
navigate
} = todoNavigator
if (process.env.NODE_ENV !== 'production') {
console.log(`todoNavigate:${todoNavigator.path}`)
}
const navigate = navigatorStack.shift()
if (navigate.nvue) {
navigate()
} else {
todoNavigator = false
return navigate()
}
export function navigateFinish () {
if (__PLATFORM__ === 'app-plus') {
// 创建预加载
const preloadWebview = createPreloadWebview()
preloadWebview.loaded ? navigate() : registerWebviewReady(preloadWebview.id, navigate)
if (!todoNavigator) {
return
}
if (todoNavigator.nvue) {
return todoNavigate()
}
preloadWebview.loaded
? todoNavigator.navigate()
: registerWebviewReady(preloadWebview.id, todoNavigate)
}
}
import {
setPreloadWebview,
initWebview,
createWebview
} from './webview'
import {
navigateStack
navigateFinish
} from './navigator'
import {
perf
} from './perf'
PAGE_CREATE
} from '../../constants'
import tabBar from '../framework/tab-bar'
import {
createPage
} from '../../page-factory'
const pages = []
export function getCurrentPages (returnAll) {
......@@ -22,24 +25,6 @@ export function getCurrentPages (returnAll) {
})
}
const pageFactory = Object.create(null)
export function definePage (name, createPageVueComponent) {
pageFactory[name] = createPageVueComponent
}
export function createPage (name, options) {
if (!pageFactory[name]) {
console.error(`${name} not found`)
}
let startTime = Date.now()
const pageVm = new (pageFactory[name]())(options)
if (process.env.NODE_ENV !== 'production') {
perf(`new ${name}`, startTime)
}
return pageVm
}
/**
* 首页需要主动registerPage,二级页面路由跳转时registerPage
*/
......@@ -62,11 +47,6 @@ export function registerPage ({
webview = createWebview(path, routeOptions)
} else {
webview = plus.webview.getWebviewById(webview.id)
// renderer:native 时,把 launchWebview 标记 preloadWebview,及 loaded,方便路由跳转识别
if (__PLATFORM__ === 'app-plus-nvue') {
webview.loaded = true
setPreloadWebview(webview)
}
}
if (routeOptions.meta.isTabBar) {
......@@ -116,19 +96,27 @@ export function registerPage ({
// 首页是 nvue 时,在 registerPage 时,执行路由堆栈
if (webview.id === '1' && routeOptions.meta.isNVue) {
webview.nvue = true
setTimeout(function () {
navigateStack(webview)
__uniConfig.onReady(function () {
navigateFinish(webview)
})
}
if (__PLATFORM__ === 'app-plus') {
if (!webview.nvue) {
const pageId = webview.id
const pagePath = path.slice(1)
pageInstance.$vm = createPage(pagePath, {
mpType: 'page',
pageId: webview.id,
pagePath
})
// 通知页面已开始创建
UniServiceJSBridge.publishHandler('vdSync', {
data: [
[PAGE_CREATE, [pageId, pagePath]]
],
options: {
timestamp: Date.now()
}
}, [pageId])
pageInstance.$vm = createPage(pagePath, pageId)
pageInstance.$vm.$scope = pageInstance
pageInstance.$vm.$mount()
}
......
export function perf (type, startTime) {
/* eslint-disable no-undef */
startTime = startTime || __UniServiceStartTime__
console.log(`[PERF] ${type} 耗时[${Date.now() - startTime}]`)
startTime = startTime || __UniServiceStartTime__
const endTime = Date.now()
console.log(`[PERF][${endTime}] ${type} 耗时[${Date.now() - startTime}]`)
}
......@@ -24,7 +24,7 @@ export function initData (Vue) {
Vue.prototype._$setData = function setData (type, data) {
this._$vd.push(type, this._$id, data)
this.$nextTick(this._$vd.flush.bind(this._$vd))
this._$vd.initialized && this.$nextTick(this._$vd.flush.bind(this._$vd))
}
Object.defineProperty(Vue.prototype, '_$vd', {
......@@ -61,6 +61,10 @@ export function initData (Vue) {
this._$data = JSON.parse(JSON.stringify(this._$newData))
console.log(`[${this._$id}] mounted ` + Date.now())
this._$setData(MOUNTED_DATA, diffData)
if (this.mpType === 'page') {
// 页面 mounted 之后,第一次同步数据
this._$vd.flush()
}
},
beforeUpdate () {
if (!this._$vd) {
......
import {
PAGE_CREATE,
PAGE_CREATED
} from '../../../constants'
......@@ -73,8 +72,7 @@ export class VDomSync {
flush () {
if (!this.initialized) {
this.initialized = true
this.batchData.unshift([PAGE_CREATE, [this.pageId]])
this.batchData.push([PAGE_CREATED, [this.pagePath]])
this.batchData.push([PAGE_CREATED, [this.pageId, this.pagePath]])
}
if (this.batchData.length) {
UniServiceJSBridge.publishHandler('vdSync', {
......
......@@ -21,6 +21,8 @@ function onWebviewReady (data, pageId) {
const isLaunchWebview = pageId === '1'
if (isLaunchWebview) { // 首页
setPreloadWebview(plus.webview.getLaunchWebview())
} else if (!preloadWebview) { // preloadWebview 不存在,重新加载一下
setPreloadWebview(plus.webview.getWebviewById(pageId))
}
if (preloadWebview.id !== pageId) {
return console.error(`webview[${pageId}] not found`)
......@@ -79,7 +81,7 @@ export function initSubscribeHandlers () {
registerPlusMessage('subscribeHandler', (data) => {
subscribeHandler(data.type, data.data, data.pageId)
})
// TODO 检测目标 preloadWebview 是否已准备好,因为 preloadWebview 准备好时,此处代码还没执行
subscribe(WEBVIEW_READY, onWebviewReady)
subscribe(WEBVIEW_UI_EVENT, onWebviewUIEvent)
}
import {
getApp,
registerApp
} from './framework/app'
uni
} from 'uni-core/service/uni'
import {
getCurrentPages
} from './framework/page'
invokeCallbackHandler
} from 'uni-helpers/api'
import {
registerConfig
} from './framework/config'
publishHandler
} from 'uni-platform/service/publish-handler'
import {
uni
} from 'uni-core/service/uni'
definePage
} from '../page-factory'
import {
invokeCallbackHandler
} from 'uni-helpers/api'
getApp,
registerApp
} from './framework/app'
import {
registerPage
} from 'uni-platform/service/register-page'
registerPage,
getCurrentPages
} from './framework/page'
import {
publishHandler
} from 'uni-platform/service/publish-handler'
import vuePlugin from './framework/plugins'
UniServiceJSBridge.publishHandler = publishHandler
UniServiceJSBridge.invokeCallbackHandler = invokeCallbackHandler
export default {
__registerConfig: registerConfig,
__vuePlugin: vuePlugin,
__definePage: definePage,
__registerApp: registerApp,
__registerPage: registerPage,
uni,
......
export {
definePage as registerPage
}
from './framework/page'
......@@ -14,12 +14,16 @@ function plusReady (callback) {
export function publishHandler (event, args = {}) {
plusReady(function () {
const pageId = plus.webview.currentWebview().id
if (process.env.NODE_ENV !== 'production') {
console.log(`[VIEW][${Date.now()}]:`, event, args, pageId)
}
plus.webview.postMessageToUniNView({
type: 'subscribeHandler',
args: {
type: event,
data: args,
pageId: plus.webview.currentWebview().id
pageId
}
}, APP_SERVICE_ID)
})
......
const pageFactory = Object.create(null)
export function definePage (name, createPageVueComponent) {
pageFactory[name] = createPageVueComponent
}
export function createPage (name, options = {}) {
return new (pageFactory[name]())(options)
const pages = []
export function getCurrentPages () {
return pages
}
export function setCurrentPage (pageId, pagePath) {
pages.length = 0
pages.push({
$page: {
id: pageId,
route: pagePath
}
})
}
......@@ -10,17 +10,25 @@ import {
} from './vdom-sync'
import {
createPage
setCurrentPage
} from '../page'
import {
getPageVueComponent
} from '../../../page-factory'
let vd
let PageVueComponent
const handleData = {
[PAGE_CREATE]: function onPageCreate (data) {
const [pageId] = data
__uniConfig.id = pageId
const [pageId, pagePath] = data
// 设置当前页面伪对象,方便其他地方使用 getCurrentPages 获取当前页面 id,route
setCurrentPage(pageId, pagePath)
// 初始化当前页面 VueComponent(生成页面样式代码)
PageVueComponent = getPageVueComponent(pagePath)
// 生成当前页面 vd
vd = new VDomSync(pageId)
},
[MOUNTED_DATA]: function onMounted (data) {
......@@ -30,11 +38,11 @@ const handleData = {
vd.updateVData.apply(vd, data)
},
[PAGE_CREATED]: function onPageCreated (data) {
const [pagePath] = data
createPage(pagePath, {
const [pageId, pagePath] = data
new PageVueComponent({
mpType: 'page',
pageId: vd.pageId,
pagePath: pagePath
pageId,
pagePath
}).$mount('#app')
}
}
......@@ -66,8 +74,6 @@ export function initData (Vue) {
if (this._$vd) {
this._$vd.initVm(this)
console.log(`[${this._$id}] beforeCreate ` + Date.now())
} else {
console.log(`[null] beforeCreate ` + Date.now())
}
}
})
......
......@@ -4,17 +4,23 @@ import {
export function initEvent (Vue) {
Vue.prototype.$handleViewEvent = function ($vueEvent, options) {
const $event = this.$handleEvent($vueEvent)
const cid = this._$id
const nid = $vueEvent.currentTarget.getAttribute('_i')
const {
nid
} = $event.options
if (!nid) {
return console.error(`[${cid}] nid not found`)
}
const $event = this.$handleEvent($vueEvent)
// 移除无属性
// 移除无属性
delete $event._processed
delete $event.mp
delete $event.preventDefault
delete $event.stopPropagation
delete $event.options
UniViewJSBridge.publishHandler(WEBVIEW_UI_EVENT, {
data: $event,
......
......@@ -8,10 +8,14 @@ import {
import {
initEvent
} from './event'
} from './event'
export default {
install (Vue, options) {
install (Vue, options) {
if (process.env.NODE_ENV !== 'production') {
Vue.config.performance = true
}
initVue(Vue)
ViewPlugin.install(Vue, options)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册