Skip to content

Commit 6d7b169

Browse files
authored
feat: multiple frames (#325)
* feat(frame and page): added frame and page component wrappers This change should allow a frame which is not topmost to still navigate a child page * feat: handle backstack caching / restoring * refactor: wip frame/page changes * feat(frame): fire frame events from the frame wrapper * feat: allow passing frame to $navigateTo BREAKING CHANGE: the options object of $navigateTo has been simplified fix #213 * refactor: add frames to sample * refactor: add <Frame> element to all samples * Fix typo error which happens in case-sensitive filesystems. * Add <Frame> node to all the samples. * refactor: remove configuration object from $start * fix: wrong conditional for v-for warning on listview * feat: inject hasRouterView property during template compilation * refactor: remove navigation call from renderer * feat: add support for <router-view> in Frame and fix wrong parent frame search function * refactor: add back button handler to sample - optional * refactor: remove old RouterPlugin * feat: <router-view> nested in <Frame> (#286) * chore: update backers * feat: Starting router chores * horror: Juggling router-views * fix: rollup * fix: Add a missing method. * add: frame transition support * fix: back transition not detected add: back transition auto flips direction (for predefined {N} transitions) - configurable with back-transition="flip|mirror" - default: flip. * chore: Remove some nextTicks that are seemingly not needed. chore: cache regexps. add: Try adding some profiling stats. * add: remove buble in order to use ES2015+ as both Android and iOS engines are quite new. add: Add some ES2015+ operators where possible add: return elements where they should be returnes add: start implementing support for push/replace/go with animation object. fix: change one deprecated command * fix: specifying Page transition on push/replace/go. chore: convert NativeScriptHistory to class. * fix: remove the back-transition setting, as it breaks page reusability. This breaks ListView events after back navigation though. * fix: the back problem (hopefully) - needs more testing first * fix: remove buble references fix: speed up default slide transitions to match Angular ones add: prop.decode modifier to decode HTML entities * fix: the page is still reactive while leaving it - causes changes to $route to be visible. * fix: really destroy the page when it should be (previous on back navigation) * fix: router back on app root * fix: iOS back button skips the router chore: some formatting * fix: rename transition props to ios:transition and android:transition * refactor: clean up unneded code * chore: build into samples dir * test: update sample app for router v2 * Sample app for testing routing with vue-router, tabs and RadSideDrawer. See #292 * fix: fixed . See #292 * feat: frame and router changes (#321) * add: dev:dist script to run ns-vue locally * chore: refactor router plugin to History only * fix: remove default on require temp: test some performance tweaks * fix: formatting * fix: the way router is used add: export router from ns-vue * fix: router replace * chore: formatting * chore: formatting * fix: better plugin and remove router from ns-vue * fix: use a simpler factory mixin for the extensibility point * fix: back transition after mingling with components * fix: possibility to stop back button handling * add: start implementing router cache * fix: simplify page * fix: more simplification * chore: remove a row * fix: linting
1 parent e72f597 commit 6d7b169

40 files changed

+1006
-449
lines changed

build/config.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const alias = require('rollup-plugin-alias')
22
const commonjs = require('rollup-plugin-commonjs')
33
const resolve = require('rollup-plugin-node-resolve')
4-
const buble = require('rollup-plugin-buble')
54
const replace = require('rollup-plugin-replace')
65
const flow = require('rollup-plugin-flow-no-whitespace')
76
const path = require('path')
@@ -65,6 +64,9 @@ const genConfig = (name) => {
6564
treeshake: {
6665
pureExternalModules: id => id.startsWith('weex')
6766
},
67+
watch: {
68+
chokidar: false
69+
},
6870
plugins: [
6971
replace({
7072
__WEEX__: false,
@@ -75,7 +77,6 @@ const genConfig = (name) => {
7577
'process.env.NS_VUE_VERSION': `'${NSVueVersion}'`
7678
}),
7779
flow(),
78-
buble(),
7980
alias(aliases),
8081
resolve(),
8182
commonjs(),

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"tdd": "jest --watch",
1414
"samples": "node build/sample-runner.js",
1515
"dev": "rollup -c build/config.js -w --o samples/app/nativescript-vue.js --environment TARGET:nativescript-vue",
16+
"dev:dist": "rollup -c build/config.js -w --o dist/index.js --environment TARGET:nativescript-vue",
1617
"build": "node build/build.js",
1718
"build:docs": "cd docs && npm run build",
1819
"prettier": "prettier --no-semi --single-quote --write \"{{platform,__test__}/**/*.js,samples/app/*.js}\"",
@@ -65,18 +66,17 @@
6566
"jest-junit": "^3.5.0",
6667
"lint-staged": "^6.1.0",
6768
"prettier": "^1.10.2",
68-
"rollup": "^0.55.3",
69+
"rollup": "^0.62.0",
6970
"rollup-plugin-alias": "^1.4.0",
70-
"rollup-plugin-buble": "^0.18.0",
71-
"rollup-plugin-commonjs": "^8.3.0",
71+
"rollup-plugin-commonjs": "^9.1.3",
7272
"rollup-plugin-flow-no-whitespace": "^1.0.0",
73-
"rollup-plugin-node-resolve": "^3.0.2",
73+
"rollup-plugin-node-resolve": "^3.3.0",
7474
"rollup-plugin-replace": "^2.0.0",
7575
"rollup-plugin-resolve-aliases": "^0.2.0",
7676
"rollup-watch": "^4.3.1",
7777
"semver": "^5.5.0",
7878
"set-value": "^2.0.0",
79-
"tns-core-modules": "4.0.0",
79+
"tns-core-modules": "4.1.0",
8080
"util-inspect": "^0.1.8",
8181
"vue": "^2.5.17"
8282
},

platform/nativescript/compiler/modules/for.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { warn } from 'core/util/debug'
66
function preTransformNode(el) {
77
let vfor
88

9-
if (normalizeElementName(el.tag) === 'listview') {
9+
if (normalizeElementName(el.tag) === 'nativelistview') {
1010
vfor = getAndRemoveAttr(el, 'v-for')
1111
delete el.attrsMap['v-for']
1212
if (process.env.NODE_ENV !== 'production' && vfor) {
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import class_ from './class'
22
import style from './style'
33
import for_ from './for'
4+
import router from './router'
45
import vTemplate from './v-template'
56
import view from './view'
67

7-
export default [class_, style, vTemplate, for_, view]
8+
export default [class_, style, vTemplate, for_, router, view]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { normalizeElementName } from '../../element-registry'
2+
import { addAttr } from 'compiler/helpers'
3+
4+
function preTransformNode(el) {
5+
if (el.tag !== 'router-view') return
6+
if (normalizeElementName(el.parent.tag) === 'nativeframe') {
7+
addAttr(el.parent, 'hasRouterView', 'true')
8+
}
9+
}
10+
11+
export default {
12+
preTransformNode
13+
}

platform/nativescript/element-registry.js

+18-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as builtInComponents from './runtime/components'
22

3-
const elementMap = new Map()
3+
const elementMap = {}
4+
const nativeRegExp = /Native/gi
5+
const dashRegExp = /-/g
46

57
const defaultViewMeta = {
68
skipAddToDom: false,
@@ -13,8 +15,8 @@ const defaultViewMeta = {
1315

1416
export function normalizeElementName(elementName) {
1517
return `native${elementName
16-
.replace(/Native/gi, '')
17-
.replace(/-/g, '')
18+
.replace(nativeRegExp, '')
19+
.replace(dashRegExp, '')
1820
.toLowerCase()}`
1921
}
2022

@@ -23,7 +25,7 @@ export function registerElement(elementName, resolver, meta) {
2325

2426
meta = Object.assign({}, defaultViewMeta, meta)
2527

26-
if (elementMap.has(normalizedName)) {
28+
if (elementMap[normalizedName]) {
2729
throw new Error(`Element for ${elementName} already registered.`)
2830
}
2931

@@ -44,7 +46,7 @@ export function registerElement(elementName, resolver, meta) {
4446
resolver: resolver,
4547
meta: meta
4648
}
47-
elementMap.set(normalizedName, entry)
49+
elementMap[normalizedName] = entry
4850
}
4951

5052
export function getElementMap() {
@@ -53,7 +55,7 @@ export function getElementMap() {
5355

5456
export function getViewClass(elementName) {
5557
const normalizedName = normalizeElementName(elementName)
56-
const entry = elementMap.get(normalizedName)
58+
const entry = elementMap[normalizedName]
5759

5860
if (!entry) {
5961
throw new TypeError(`No known component for element ${elementName}.`)
@@ -70,7 +72,7 @@ export function getViewMeta(elementName) {
7072
const normalizedName = normalizeElementName(elementName)
7173

7274
let meta = defaultViewMeta
73-
const entry = elementMap.get(normalizedName)
75+
const entry = elementMap[normalizedName]
7476

7577
if (entry && entry.meta) {
7678
meta = entry.meta
@@ -80,7 +82,7 @@ export function getViewMeta(elementName) {
8082
}
8183

8284
export function isKnownView(elementName) {
83-
return elementMap.has(normalizeElementName(elementName))
85+
return elementMap[normalizeElementName(elementName)]
8486
}
8587

8688
registerElement(
@@ -214,8 +216,10 @@ registerElement(
214216
}
215217
)
216218
registerElement('Page', () => require('tns-core-modules/ui/page').Page, {
217-
skipAddToDom: true
219+
skipAddToDom: true,
220+
component: builtInComponents.Page
218221
})
222+
219223
registerElement(
220224
'Placeholder',
221225
() => require('tns-core-modules/ui/placeholder').Placeholder
@@ -360,8 +364,9 @@ registerElement(
360364

361365
registerElement('Frame', () => require('tns-core-modules/ui/frame').Frame, {
362366
insertChild(parentNode, childNode, atIndex) {
363-
if (normalizeElementName(childNode.tagName) === 'nativepage') {
364-
parentNode.nativeView.navigate({ create: () => childNode.nativeView })
365-
}
366-
}
367+
// if (normalizeElementName(childNode.tagName) === 'nativepage') {
368+
// parentNode.nativeView.navigate({ create: () => childNode.nativeView })
369+
// }
370+
},
371+
component: builtInComponents.Frame
367372
})

platform/nativescript/framework.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import application from 'tns-core-modules/application'
99
import Vue from './runtime/index'
1010
import ModalPlugin from './plugins/modal-plugin'
1111
import NavigatorPlugin from './plugins/navigator-plugin'
12-
import RouterPlugin from './plugins/router-plugin'
1312

1413
import { setVue } from './util'
1514

@@ -19,18 +18,19 @@ setVue(Vue)
1918

2019
Vue.use(ModalPlugin)
2120
Vue.use(NavigatorPlugin)
22-
Vue.use(RouterPlugin)
21+
22+
const newLineRegExp = /\\n/g
2323

2424
console.log = (function(log, inspect, Vue) {
25-
return function() {
26-
return log.apply(
25+
return function(...args) {
26+
return log.call(
2727
this,
28-
Array.prototype.map.call(arguments, function(arg) {
28+
...Array.prototype.map.call(args, function(arg) {
2929
return inspect(arg, {
3030
depth: 2,
3131
colors: Vue.config.debug,
3232
showHidden: true
33-
}).replace(/\\n/g, '\n')
33+
}).replace(newLineRegExp, '\n')
3434
})
3535
)
3636
}

platform/nativescript/plugins/navigator-plugin.js

+42-23
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,52 @@
1-
import { topmost } from 'tns-core-modules/ui/frame'
2-
import { ensurePage } from '../util'
1+
import { isObject, isDef, isPrimitive } from 'shared/util'
2+
import { getFrame } from '../util/frame'
3+
import { getFrameById } from 'tns-core-modules/ui/frame'
4+
5+
function getFrameInstance(frame) {
6+
// get the frame that we need to navigate
7+
// this can be a frame id (String)
8+
// a Vue ref to a frame
9+
// a Frame ViewNode
10+
// or a Frame instance
11+
if (isObject(frame) && isDef(frame.$el)) {
12+
frame = frame.$el.nativeView
13+
} else if (isPrimitive(frame)) {
14+
frame = getFrameById(frame)
15+
} else if (isDef(frame.nativeView)) {
16+
frame = frame.nativeView
17+
}
18+
// finally get the component instance for this frame
19+
return getFrame(frame.id)
20+
}
321

422
export default {
523
install(Vue) {
6-
Vue.navigateBack = Vue.prototype.$navigateBack = function() {
7-
return topmost().goBack()
8-
}
24+
Vue.prototype.$navigateBack = function(options) {
25+
const defaultOptions = {
26+
frame: 'default'
27+
}
28+
options = Object.assign({}, defaultOptions, options)
29+
const frame = getFrameInstance(options.frame)
930

10-
Vue.navigateTo = Vue.prototype.$navigateTo = function(
11-
component,
12-
options = {},
13-
pageCb = () => {}
14-
) {
15-
return new Promise(resolve => {
16-
const navigationEntry = {
17-
create() {
18-
const vm = new (Vue.extend(component))(options.context)
19-
20-
vm.$mount()
21-
const pageInstance = ensurePage(vm.$el, vm)
31+
frame.back()
32+
}
2233

23-
pageCb(pageInstance)
24-
resolve(pageInstance)
34+
Vue.prototype.$navigateTo = function(component, options) {
35+
const defaultOptions = {
36+
frame: 'default'
37+
}
38+
// build options object with defaults
39+
options = Object.assign({}, defaultOptions, options)
2540

26-
return pageInstance
27-
}
28-
}
41+
return new Promise(resolve => {
42+
const frame = getFrameInstance(options.frame)
43+
const page = new Vue({
44+
parent: this,
45+
render: h => h(component, { props: options.props })
46+
}).$mount().$el.nativeView
2947

30-
topmost().navigate(Object.assign({}, navigationEntry, options))
48+
frame.navigate(Object.assign({}, options, { create: () => page }))
49+
resolve(page)
3150
})
3251
}
3352
}

0 commit comments

Comments
 (0)