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

wip(app): nvue scroll-view

上级 e3b2f59d
...@@ -199,6 +199,7 @@ declare namespace UniApp { ...@@ -199,6 +199,7 @@ declare namespace UniApp {
backgroundColor?: string backgroundColor?: string
maxWidth?: string | number maxWidth?: string | number
// app-plus // app-plus
scrollIndicator?: 'none'
animationType?: string animationType?: string
animationDuration?: number animationDuration?: number
subNVues?: PagesJsonPageStyleSubNVue[] subNVues?: PagesJsonPageStyleSubNVue[]
......
...@@ -24,6 +24,7 @@ import { transformText } from './transforms/transformText' ...@@ -24,6 +24,7 @@ import { transformText } from './transforms/transformText'
import { createConfigResolved } from '../../plugin/configResolved' import { createConfigResolved } from '../../plugin/configResolved'
import { defaultNVueRpx2Unit } from '@dcloudio/uni-shared' import { defaultNVueRpx2Unit } from '@dcloudio/uni-shared'
import { external, globals } from '../utils' import { external, globals } from '../utils'
import { transformRootNode } from './transforms/transformRootNode'
const uTags = { const uTags = {
text: 'u-text', text: 'u-text',
...@@ -38,6 +39,7 @@ const uTags = { ...@@ -38,6 +39,7 @@ const uTags = {
export function initNVueNodeTransforms() { export function initNVueNodeTransforms() {
// 优先级必须确保 renderWhole > appendAsTree // 优先级必须确保 renderWhole > appendAsTree
return [ return [
transformRootNode,
createTransformTag(uTags), createTransformTag(uTags),
transformText, transformText,
transformVideo, transformVideo,
......
import { createBindDirectiveNode } from '@dcloudio/uni-cli-shared'
import {
AttributeNode,
createSimpleExpression,
DirectiveNode,
ElementNode,
ElementTypes,
locStub,
NodeTransform,
NodeTypes,
RootNode,
TemplateChildNode,
} from '@vue/compiler-core'
const SCROLLER_COMPONENTS = [
'list',
'scroller',
'scroll-view',
'waterfall',
'recycle-list',
]
export const transformRootNode: NodeTransform = (node, context) => {
if (node.type !== NodeTypes.ROOT || !context.bindingMetadata.__pageOptions) {
return
}
const { disableScroll, scrollIndicator } = context.bindingMetadata
.__pageOptions as {
disableScroll?: boolean
scrollIndicator?: 'none'
}
// 禁用滚动,或已包含滚动元素
if (disableScroll || hasScrollerElement(node)) {
return wrapperByView(node)
}
return wrapperByScrollView(node, { scrollIndicator })
}
function hasScrollerElement(node: RootNode) {
return node.children.some((child) => {
if (child.type === NodeTypes.ELEMENT) {
return SCROLLER_COMPONENTS.includes(child.tag)
}
})
}
function wrapperByScrollView(
node: RootNode,
{ scrollIndicator }: { scrollIndicator?: 'none' }
) {
node.children = [
createElement(
'scroll-view',
createScrollViewProps({ scrollIndicator }),
node.children
),
]
}
const trueExpr = createSimpleExpression('true')
const falseExpr = createSimpleExpression('false')
function createScrollViewProps({
scrollIndicator,
}: {
scrollIndicator?: 'none'
}) {
return [
createBindDirectiveNode('scrollY', trueExpr),
createBindDirectiveNode(
'showScrollbar',
scrollIndicator === 'none' ? falseExpr : trueExpr
),
createBindDirectiveNode('enableBackToTop', trueExpr),
createBindDirectiveNode('bubble', trueExpr),
createBindDirectiveNode('style', `{flexDirection:'column'}`),
]
}
/**
* 目前暂不支持多节点,故发现多节点时,自动补充一个 view 根节点
* @param node
*/
function wrapperByView(node: RootNode) {
if (node.children.length > 1) {
node.children = [createElement('view', [], node.children)]
}
}
function createElement(
tag: string,
props: (AttributeNode | DirectiveNode)[],
children: TemplateChildNode[]
): ElementNode {
return {
type: NodeTypes.ELEMENT,
ns: 0,
tag,
isSelfClosing: false,
props,
children,
tagType: ElementTypes.ELEMENT,
codegenNode: undefined,
loc: locStub,
}
}
import { NodeTransform, NodeTypes } from '@vue/compiler-core'
export const transformScrollView: NodeTransform = (node, context) => {
if (node.type !== NodeTypes.ROOT) {
return
}
console.log(context)
}
import path from 'path' import path from 'path'
import { Plugin } from 'vite' import type { Plugin } from 'vite'
import type { CompilerOptions } from '@vue/compiler-sfc'
import { import {
defineUniPagesJsonPlugin, defineUniPagesJsonPlugin,
normalizeAppConfigService, normalizeAppConfigService,
...@@ -9,8 +9,17 @@ import { ...@@ -9,8 +9,17 @@ import {
getLocaleFiles, getLocaleFiles,
normalizeAppNVuePagesJson, normalizeAppNVuePagesJson,
APP_CONFIG_SERVICE, APP_CONFIG_SERVICE,
resolveBuiltIn,
normalizePath,
} from '@dcloudio/uni-cli-shared' } from '@dcloudio/uni-cli-shared'
interface NVuePages {
[filename: string]: {
disableScroll?: boolean
scrollIndicator?: 'none'
}
}
export function uniPagesJsonPlugin({ export function uniPagesJsonPlugin({
renderer, renderer,
appService, appService,
...@@ -18,6 +27,11 @@ export function uniPagesJsonPlugin({ ...@@ -18,6 +27,11 @@ export function uniPagesJsonPlugin({
renderer?: 'native' renderer?: 'native'
appService: boolean appService: boolean
}): Plugin { }): Plugin {
const nvuePages: NVuePages = {}
// 仅编译nvue页面时重写
if (!appService) {
rewriteBindingMetadata(nvuePages)
}
return defineUniPagesJsonPlugin((opts) => { return defineUniPagesJsonPlugin((opts) => {
return { return {
name: 'uni:app-nvue-pages-json', name: 'uni:app-nvue-pages-json',
...@@ -35,9 +49,14 @@ export function uniPagesJsonPlugin({ ...@@ -35,9 +49,14 @@ export function uniPagesJsonPlugin({
const pagesJson = normalizePagesJson(code, process.env.UNI_PLATFORM) const pagesJson = normalizePagesJson(code, process.env.UNI_PLATFORM)
pagesJson.pages.forEach((page) => { pagesJson.pages.forEach((page) => {
if (page.style.isNVue) { if (page.style.isNVue) {
this.addWatchFile( const filename = normalizePath(
path.resolve(process.env.UNI_INPUT_DIR, page.path + '.nvue') path.resolve(process.env.UNI_INPUT_DIR, page.path + '.nvue')
) )
nvuePages[filename] = {
disableScroll: page.style.disableScroll,
scrollIndicator: page.style.scrollIndicator,
}
this.addWatchFile(filename)
} }
}) })
if (renderer === 'native' && appService) { if (renderer === 'native' && appService) {
...@@ -62,3 +81,20 @@ export function uniPagesJsonPlugin({ ...@@ -62,3 +81,20 @@ export function uniPagesJsonPlugin({
} }
}) })
} }
/**
* 在 BindingMetadata 中补充页面标记
*/
function rewriteBindingMetadata(nvuePages: NVuePages) {
const compilerDom = require(resolveBuiltIn('@vue/compiler-dom'))
const { compile } = compilerDom
compilerDom.compile = (template: string, options: CompilerOptions = {}) => {
if (options.filename && options.bindingMetadata) {
if (nvuePages[options.filename]) {
;(options.bindingMetadata as any).__pageOptions =
nvuePages[options.filename]
}
}
return compile(template, options)
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册