提交 018baeab 编写于 作者: fxy060608's avatar fxy060608

feat: support page selector

上级 c26c15de
...@@ -3515,8 +3515,10 @@ function normalizeRouteKey(path, id2) { ...@@ -3515,8 +3515,10 @@ function normalizeRouteKey(path, id2) {
function useKeepAliveRoute() { function useKeepAliveRoute() {
const route = useRoute(); const route = useRoute();
const routeKey = computed(() => normalizeRouteKey(route.path, history.state.__id__ || 1)); const routeKey = computed(() => normalizeRouteKey(route.path, history.state.__id__ || 1));
const isTabBar = computed(() => route.meta.isTabBar);
return { return {
routeKey, routeKey,
isTabBar,
routeCache routeCache
}; };
} }
...@@ -3541,16 +3543,7 @@ const routeCache = { ...@@ -3541,16 +3543,7 @@ const routeCache = {
} }
}; };
function isTabBarVNode(vnode) { function isTabBarVNode(vnode) {
if (!hasOwn$1(vnode, "__isTabBar")) { return vnode.props.type === "tabBar";
const {component} = vnode;
if (component && component.refs.page) {
const vm = component.refs.page;
if (vm.$page) {
vnode.__isTabBar = vm.__isTabBar;
}
}
}
return vnode.__isTabBar;
} }
function pruneRouteCache(key) { function pruneRouteCache(key) {
const pageId = parseInt(key.split(SEP)[1]); const pageId = parseInt(key.split(SEP)[1]);
...@@ -3570,9 +3563,33 @@ function pruneRouteCache(key) { ...@@ -3570,9 +3563,33 @@ function pruneRouteCache(key) {
}); });
} }
function onPageShow(instance2, pageMeta) { function onPageShow(instance2, pageMeta) {
updateBodyScopeId(instance2);
updateCurPageCssVar(pageMeta); updateCurPageCssVar(pageMeta);
initPageScrollListener(instance2, pageMeta); initPageScrollListener(instance2, pageMeta);
} }
function onPageReady(instance2) {
const scopeId = getScopeId(instance2);
scopeId && updateCurPageBodyScopeId(scopeId);
}
function updateCurPageBodyScopeId(scopeId) {
const pageBodyEl = document.querySelector("uni-page-body");
if (pageBodyEl) {
pageBodyEl.setAttribute(scopeId, "");
} else if (process.env.NODE_ENV !== "production") {
console.warn("uni-page-body not found");
}
}
function getScopeId(instance2) {
return instance2.type.__scopeId;
}
let curScopeId;
function updateBodyScopeId(instance2) {
const scopeId = getScopeId(instance2);
const {body} = document;
curScopeId && body.removeAttribute(curScopeId);
scopeId && body.setAttribute(scopeId, "");
curScopeId = scopeId;
}
let curScrollListener; let curScrollListener;
function initPageScrollListener(instance2, pageMeta) { function initPageScrollListener(instance2, pageMeta) {
document.removeEventListener("touchmove", disableScrollListener); document.removeEventListener("touchmove", disableScrollListener);
...@@ -3698,13 +3715,14 @@ function setupPage(comp) { ...@@ -3698,13 +3715,14 @@ function setupPage(comp) {
} }
const pageMeta = usePageMeta(); const pageMeta = usePageMeta();
onBeforeMount(() => { onBeforeMount(() => {
const {onLoad, onShow} = instance2;
onPageShow(instance2, pageMeta); onPageShow(instance2, pageMeta);
const {onLoad, onShow} = instance2;
onLoad && invokeArrayFns$1(onLoad, decodedQuery(route.query)); onLoad && invokeArrayFns$1(onLoad, decodedQuery(route.query));
instance2.__isVisible = true; instance2.__isVisible = true;
onShow && invokeArrayFns$1(onShow); onShow && invokeArrayFns$1(onShow);
}); });
onMounted(() => { onMounted(() => {
onPageReady(instance2);
const {onReady} = instance2; const {onReady} = instance2;
onReady && invokeArrayFns$1(onReady); onReady && invokeArrayFns$1(onReady);
}); });
...@@ -12698,14 +12716,13 @@ function removeNonTabBarPages() { ...@@ -12698,14 +12716,13 @@ function removeNonTabBarPages() {
const keys = pagesMap.keys(); const keys = pagesMap.keys();
for (const routeKey of keys) { for (const routeKey of keys) {
const page = pagesMap.get(routeKey); const page = pagesMap.get(routeKey);
const pageMeta = page.$page.meta; if (!page.__isTabBar) {
if (!pageMeta.isTabBar) {
removePage(routeKey); removePage(routeKey);
} else { } else {
page.$.__isActive = false; page.$.__isActive = false;
} }
} }
if (curTabBarPageVm.$page.meta.isTabBar) { if (curTabBarPageVm.__isTabBar) {
curTabBarPageVm.$.__isVisible = false; curTabBarPageVm.$.__isVisible = false;
invokeHook(curTabBarPageVm, "onHide"); invokeHook(curTabBarPageVm, "onHide");
} }
...@@ -13447,15 +13464,20 @@ function createTabBarTsx(showTabBar2) { ...@@ -13447,15 +13464,20 @@ function createTabBarTsx(showTabBar2) {
function createPageVNode() { function createPageVNode() {
return createVNode(__uniRoutes[0].component); return createVNode(__uniRoutes[0].component);
} }
function createRouterViewVNode(keepAliveRoute) { function createRouterViewVNode({
routeKey,
isTabBar,
routeCache: routeCache2
}) {
return createVNode(RouterView, null, { return createVNode(RouterView, null, {
default: withCtx(({ default: withCtx(({
Component Component
}) => [(openBlock(), createBlock(KeepAlive, { }) => [(openBlock(), createBlock(KeepAlive, {
matchBy: "key", matchBy: "key",
cache: keepAliveRoute.routeCache cache: routeCache2
}, [(openBlock(), createBlock(resolveDynamicComponent(Component), { }, [(openBlock(), createBlock(resolveDynamicComponent(Component), {
key: keepAliveRoute.routeKey.value type: isTabBar.value ? "tabBar" : "",
key: routeKey.value
}))], 1032, ["cache"]))]), }))], 1032, ["cache"]))]),
_: 1 _: 1
}); });
......
...@@ -118,19 +118,22 @@ function createPageVNode() { ...@@ -118,19 +118,22 @@ function createPageVNode() {
return createVNode(__uniRoutes[0].component) return createVNode(__uniRoutes[0].component)
} }
function createRouterViewVNode( function createRouterViewVNode({
keepAliveRoute: ReturnType<typeof useKeepAliveRoute> routeKey,
) { isTabBar,
routeCache,
}: ReturnType<typeof useKeepAliveRoute>) {
return createVNode(RouterView, null, { return createVNode(RouterView, null, {
default: withCtx(({ Component }: { Component: unknown }) => [ default: withCtx(({ Component }: { Component: unknown }) => [
(openBlock(), (openBlock(),
createBlock( createBlock(
KeepAlive, KeepAlive,
{ matchBy: 'key', cache: keepAliveRoute.routeCache }, { matchBy: 'key', cache: routeCache },
[ [
(openBlock(), (openBlock(),
createBlock(resolveDynamicComponent(Component), { createBlock(resolveDynamicComponent(Component), {
key: keepAliveRoute.routeKey.value, type: isTabBar.value ? 'tabBar' : '',
key: routeKey.value,
})), })),
], ],
1032 /* PROPS, DYNAMIC_SLOTS */, 1032 /* PROPS, DYNAMIC_SLOTS */,
......
...@@ -15,7 +15,7 @@ import { useRouter } from 'vue-router' ...@@ -15,7 +15,7 @@ import { useRouter } from 'vue-router'
import { decodedQuery } from '@dcloudio/uni-shared' import { decodedQuery } from '@dcloudio/uni-shared'
import { LayoutComponent } from '../..' import { LayoutComponent } from '../..'
import { initApp } from './app' import { initApp } from './app'
import { initPage, onPageShow } from './page' import { initPage, onPageShow, onPageReady } from './page'
import { usePageMeta, usePageRoute } from './provide' import { usePageMeta, usePageRoute } from './provide'
interface SetupComponentOptions { interface SetupComponentOptions {
...@@ -61,13 +61,14 @@ export function setupPage(comp: any) { ...@@ -61,13 +61,14 @@ export function setupPage(comp: any) {
} }
const pageMeta = usePageMeta() const pageMeta = usePageMeta()
onBeforeMount(() => { onBeforeMount(() => {
const { onLoad, onShow } = instance
onPageShow(instance, pageMeta) onPageShow(instance, pageMeta)
const { onLoad, onShow } = instance
onLoad && invokeArrayFns(onLoad, decodedQuery(route.query)) onLoad && invokeArrayFns(onLoad, decodedQuery(route.query))
instance.__isVisible = true instance.__isVisible = true
onShow && invokeArrayFns(onShow) onShow && invokeArrayFns(onShow)
}) })
onMounted(() => { onMounted(() => {
onPageReady(instance)
const { onReady } = instance const { onReady } = instance
onReady && invokeArrayFns(onReady) onReady && invokeArrayFns(onReady)
}) })
......
...@@ -6,7 +6,6 @@ import { ...@@ -6,7 +6,6 @@ import {
ComponentPublicInstance, ComponentPublicInstance,
ComponentInternalInstance, ComponentInternalInstance,
} from 'vue' } from 'vue'
import { hasOwn } from '@vue/shared'
import { useRoute, RouteLocationNormalizedLoaded } from 'vue-router' import { useRoute, RouteLocationNormalizedLoaded } from 'vue-router'
import { import {
invokeHook, invokeHook,
...@@ -120,8 +119,10 @@ export function useKeepAliveRoute() { ...@@ -120,8 +119,10 @@ export function useKeepAliveRoute() {
const routeKey = computed(() => const routeKey = computed(() =>
normalizeRouteKey(route.path, history.state.__id__ || 1) normalizeRouteKey(route.path, history.state.__id__ || 1)
) )
const isTabBar = computed(() => route.meta.isTabBar)
return { return {
routeKey, routeKey,
isTabBar,
routeCache, routeCache,
} }
} }
...@@ -162,16 +163,7 @@ const routeCache: KeepAliveCache = { ...@@ -162,16 +163,7 @@ const routeCache: KeepAliveCache = {
} }
function isTabBarVNode(vnode: VNode): boolean { function isTabBarVNode(vnode: VNode): boolean {
if (!hasOwn(vnode, '__isTabBar')) { return vnode.props!.type === 'tabBar'
const { component } = vnode
if (component && component.refs.page) {
const vm = component.refs.page as ComponentPublicInstance
if (vm.$page) {
;(vnode as any).__isTabBar = vm.__isTabBar
}
}
}
return (vnode as any).__isTabBar
} }
function pruneRouteCache(key: string) { function pruneRouteCache(key: string) {
...@@ -197,10 +189,38 @@ export function onPageShow( ...@@ -197,10 +189,38 @@ export function onPageShow(
instance: ComponentInternalInstance, instance: ComponentInternalInstance,
pageMeta: UniApp.PageRouteMeta pageMeta: UniApp.PageRouteMeta
) { ) {
updateBodyScopeId(instance)
updateCurPageCssVar(pageMeta) updateCurPageCssVar(pageMeta)
initPageScrollListener(instance, pageMeta) initPageScrollListener(instance, pageMeta)
} }
export function onPageReady(instance: ComponentInternalInstance) {
const scopeId = getScopeId(instance)
scopeId && updateCurPageBodyScopeId(scopeId)
}
function updateCurPageBodyScopeId(scopeId: string) {
const pageBodyEl = document.querySelector('uni-page-body')
if (pageBodyEl) {
pageBodyEl.setAttribute(scopeId, '')
} else if (__DEV__) {
console.warn('uni-page-body not found')
}
}
function getScopeId(instance: ComponentInternalInstance) {
return (instance.type as any).__scopeId
}
let curScopeId: string
function updateBodyScopeId(instance: ComponentInternalInstance) {
const scopeId = getScopeId(instance)
const { body } = document
curScopeId && body.removeAttribute(curScopeId!)
scopeId && body.setAttribute(scopeId, '')
curScopeId = scopeId!
}
let curScrollListener: (evt: Event) => any let curScrollListener: (evt: Event) => any
function initPageScrollListener( function initPageScrollListener(
instance: ComponentInternalInstance, instance: ComponentInternalInstance,
......
...@@ -19,14 +19,13 @@ function removeNonTabBarPages() { ...@@ -19,14 +19,13 @@ function removeNonTabBarPages() {
const keys = pagesMap.keys() const keys = pagesMap.keys()
for (const routeKey of keys) { for (const routeKey of keys) {
const page = pagesMap.get(routeKey) as ComponentPublicInstance const page = pagesMap.get(routeKey) as ComponentPublicInstance
const pageMeta = page.$page.meta if (!page.__isTabBar) {
if (!pageMeta.isTabBar) {
removePage(routeKey) removePage(routeKey)
} else { } else {
page.$.__isActive = false page.$.__isActive = false
} }
} }
if (curTabBarPageVm.$page.meta.isTabBar) { if (curTabBarPageVm.__isTabBar) {
curTabBarPageVm.$.__isVisible = false curTabBarPageVm.$.__isVisible = false
invokeHook(curTabBarPageVm, 'onHide') invokeHook(curTabBarPageVm, 'onHide')
} }
......
...@@ -49,6 +49,7 @@ export default /*#__PURE__*/ defineComponent({ ...@@ -49,6 +49,7 @@ export default /*#__PURE__*/ defineComponent({
}) })
return () => { return () => {
const { title, content, showCancel, confirmText, confirmColor } = props const { title, content, showCancel, confirmText, confirmColor } = props
// TODO vue3 似乎有bug,不指定passive时,应该默认加上passive:false,否则浏览器会报警告,先看看vue3 会不会修复,若不修复,可以考虑手动addEventListener
return ( return (
<Transition name="uni-fade"> <Transition name="uni-fade">
<uni-modal v-show={visible.value} onTouchmove={onEventPrevent}> <uni-modal v-show={visible.value} onTouchmove={onEventPrevent}>
......
...@@ -4,11 +4,14 @@ import { VitePluginUniResolvedOptions } from '..' ...@@ -4,11 +4,14 @@ import { VitePluginUniResolvedOptions } from '..'
import { uniapp } from '../utils' import { uniapp } from '../utils'
export function createCss( export function createCss(
_options: VitePluginUniResolvedOptions options: VitePluginUniResolvedOptions
): UserConfig['css'] { ): UserConfig['css'] {
return { return {
postcss: { postcss: {
plugins: [uniapp(), autoprefixer()], plugins: [
uniapp({ page: options.platform === 'h5' ? 'uni-page-body' : 'body' }),
autoprefixer(),
],
}, },
preprocessorOptions: { preprocessorOptions: {
scss: {}, scss: {},
......
import { Rule, Declaration, Plugin } from 'postcss' import { extend } from '@vue/shared'
import { rule, Rule, Declaration, Plugin } from 'postcss'
import selectorParser from 'postcss-selector-parser' import selectorParser from 'postcss-selector-parser'
import { import {
isBuiltInComponent, isBuiltInComponent,
...@@ -6,30 +7,73 @@ import { ...@@ -6,30 +7,73 @@ import {
} from '@dcloudio/uni-shared' } from '@dcloudio/uni-shared'
interface UniAppCssProcessorOptions { interface UniAppCssProcessorOptions {
page?: boolean page?: string
unit: string // 目标单位,默认rem unit?: string // 目标单位,默认rem
unitRatio: number // 单位转换比例,默认10/320 unitRatio?: number // 单位转换比例,默认10/320
unitPrecision: number // 单位精度,默认5 unitPrecision?: number // 单位精度,默认5
} }
const defaultUniAppCssProcessorOptions = { const defaultUniAppCssProcessorOptions = {
page: false, page: 'body',
unit: 'rem', unit: 'rem',
unitRatio: 10 / 320, unitRatio: 10 / 320,
unitPrecision: 5, unitPrecision: 5,
} }
function transform(selector: selectorParser.Node) { const BG_PROPS = [
if (selector.type === 'tag' && isBuiltInComponent(selector.value)) { 'background',
selector.value = COMPONENT_SELECTOR_PREFIX + selector.value 'background-clip',
'background-color',
'background-image',
'background-origin',
'background-position',
'background-repeat',
'background-size',
'background-attachment',
]
function transform(
selector: selectorParser.Node,
opts: UniAppCssProcessorOptions,
state: { bg: boolean }
) {
if (selector.type !== 'tag') {
return
}
const { value } = selector
if (isBuiltInComponent(value)) {
selector.value = COMPONENT_SELECTOR_PREFIX + value
} else if (value === 'page') {
const { page } = opts
if (!page) {
return
}
selector.value = page
if (page !== 'body') {
state.bg = true
}
}
}
function createBodyBackgroundRule(origRule: Rule) {
const bgDecls: Declaration[] = []
origRule.walkDecls((decl) => {
if (BG_PROPS.indexOf(decl.prop) !== -1) {
bgDecls.push(decl.clone())
}
})
if (bgDecls.length) {
origRule.after(rule({ selector: 'body' }).append(bgDecls))
} }
} }
function walkRules(opts: UniAppCssProcessorOptions) { function walkRules(opts: UniAppCssProcessorOptions) {
return (rule: Rule) => { return (rule: Rule) => {
const state = { bg: false }
rule.selector = selectorParser((selectors) => rule.selector = selectorParser((selectors) =>
selectors.walk((selector) => transform(selector)) selectors.walk((selector) => transform(selector, opts, state))
).processSync(rule.selector) ).processSync(rule.selector)
state.bg && createBodyBackgroundRule(rule)
} }
} }
...@@ -44,7 +88,7 @@ function toFixed(number: number, precision: number) { ...@@ -44,7 +88,7 @@ function toFixed(number: number, precision: number) {
return (Math.round(wholeNumber / 10) * 10) / multiplier return (Math.round(wholeNumber / 10) * 10) / multiplier
} }
function walkDecls(opts: UniAppCssProcessorOptions) { function walkDecls(opts: Required<UniAppCssProcessorOptions>) {
return (decl: Declaration) => { return (decl: Declaration) => {
const { value } = decl const { value } = decl
if (value.indexOf('rpx') === -1 && value.indexOf('upx') === -1) { if (value.indexOf('rpx') === -1 && value.indexOf('upx') === -1) {
...@@ -61,18 +105,14 @@ function walkDecls(opts: UniAppCssProcessorOptions) { ...@@ -61,18 +105,14 @@ function walkDecls(opts: UniAppCssProcessorOptions) {
} }
export const uniapp = (opts?: UniAppCssProcessorOptions) => { export const uniapp = (opts?: UniAppCssProcessorOptions) => {
const options = Object.assign( const options = extend({}, defaultUniAppCssProcessorOptions, opts || {})
{},
defaultUniAppCssProcessorOptions,
opts || {}
)
return { return {
postcssPlugin: 'uni-app', postcssPlugin: 'uni-app',
prepare() { prepare() {
return { return {
OnceExit(root) { OnceExit(root) {
root.walkRules(walkRules(options))
root.walkDecls(walkDecls(options)) root.walkDecls(walkDecls(options))
root.walkRules(walkRules(options))
}, },
} }
}, },
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册