tdesign-mobile-vue
Version:
tdesign-mobile-vue
1 lines • 13.5 kB
Source Map (JSON)
{"version":3,"file":"tnode.mjs","sources":["../../src/hooks/tnode.ts"],"sourcesContent":["import { h, getCurrentInstance, ComponentInternalInstance, VNode } from 'vue';\nimport { camelCase, kebabCase, isFunction } from 'lodash-es';\n\nimport { getDefaultNode, getParams, OptionsType, JSXRenderContext, getSlotFirst } from './render-tnode';\nimport { hasOwn } from '../_common/js/utils/general';\n\nfunction handleSlots(instance: ComponentInternalInstance, name: string, params: Record<string, any>) {\n // 2023-08 new Function 触发部分使用场景安全策略问题(Chrome插件/eletron等)\n // // 每个 slots 需要单独的 h 函数 否则直接assign会重复把不同 slots 的 params 都注入\n // const finalParams = new Function('return ' + h.toString())();\n // if (params) {\n // Object.assign(finalParams, params);\n // }\n\n // 检查是否存在 驼峰命名 的插槽(过滤注释节点)\n let node = instance.slots[camelCase(name)]?.(params);\n if (node && node.filter((t) => t.type.toString?.() !== 'Symbol(v-cmt)').length) return node;\n // 检查是否存在 中划线命名 的插槽\n node = instance.slots[kebabCase(name)]?.(params);\n if (node && node.filter((t) => t.type.toString?.() !== 'Symbol(v-cmt)').length) return node;\n return null;\n}\n\n/**\n * 是否为空节点,需要过滤掉注释节点。注释节点也会被认为是空节点\n */\nfunction isEmptyNode(node: any) {\n if ([undefined, null, ''].includes(node)) return true;\n const innerNodes = node instanceof Array ? node : [node];\n const r = innerNodes.filter((node) => node?.type?.toString() !== 'Symbol(Comment)');\n return !r.length;\n}\n\n// TODO 可以把这里移动到 utils 中\n/**\n * 检查用户是否有主动传 prop\n * @param instance 组件实例\n * @param propName prop 名称\n * @returns boolean\n */\nfunction isPropExplicitlySet(instance: ComponentInternalInstance, propName: string) {\n const vProps = instance?.vnode.props || {};\n return hasOwn(vProps, camelCase(propName)) || hasOwn(vProps, kebabCase(propName));\n}\n\n/**\n/**\n * 通过 JSX 的方式渲染 TNode,props 和 插槽同时处理,也能处理默认值为 true 则渲染默认节点的情况\n * 优先级:用户注入的 props 值 > slot > 默认 props 值\n * 如果 props 值为 true ,则使用插槽渲染。如果也没有插槽的情况下,则使用 defaultNode 渲染\n * @example const renderTNodeJSX = useTNodeJSX()\n * @return () => {}\n * @param name 插槽和属性名称\n * @param options 值可能为默认渲染节点,也可能是默认渲染节点和参数的集合\n * @example renderTNodeJSX('closeBtn') 优先级 props function 大于 插槽\n * @example renderTNodeJSX('closeBtn', <close-icon />)。 当属性值为 true 时则渲染 <close-icon />\n * @example renderTNodeJSX('closeBtn', { defaultNode: <close-icon />, params })。 params 为渲染节点时所需的参数\n */\nexport const useTNodeJSX = () => {\n const instance = getCurrentInstance();\n return function (name: string, options?: OptionsType) {\n // 渲染节点时所需的参数\n const renderParams = getParams(options);\n // 默认渲染节点\n // TODO 这里需要讨论,这里的默认节点规则是什么呢? pp test:unit image-viewer pp test:unit Collapse\n const defaultNode = getDefaultNode(options);\n // 是否显示设置 slot 优先\n const isSlotFirst = getSlotFirst(options);\n // 插槽\n const renderSlot = instance.slots[camelCase(name)] || instance.slots[kebabCase(name)];\n\n if (isSlotFirst && renderSlot) {\n // 1. 如果显示设置了 slot 优先,并且存在 slot,那么优先使用 slot\n return handleSlots(instance, name, renderParams);\n }\n // 2. 否者按照 用户主动传入的 props 值 > slot > 默认 props 值\n // 2.1 处理主动传入的 prop\n if (isPropExplicitlySet(instance, name)) {\n // 2.1.1 如果有传,那么优先使用 prop 的值\n const propsNode = instance.props[camelCase(name)] || instance.props[kebabCase(name)];\n // 如果该属性的类型有多种且包含 Boolean 和 Slot 的情况下,处理 boolean casting true 的场景\n // https://vuejs.org/guide/components/props.html#boolean-casting\n const types = instance.type.props[name]?.type;\n if (types?.length > 1) {\n if (types.includes(Boolean) && types.includes(Function)) {\n if (propsNode === '' && !renderSlot) return defaultNode;\n }\n }\n // 2.1.2 如果 prop 的值为 false 或者 null,那么直接不渲染\n if (propsNode === false || propsNode === null) return;\n // 2.1.3 如果 prop 的值为 true,那么使用 slot 渲染\n if (propsNode === true) {\n return handleSlots(instance, name, renderParams) || defaultNode;\n }\n // 2.1.4 如果 prop 的值为函数,那么执行函数\n if (isFunction(propsNode)) return propsNode(h, renderParams);\n // 2.1.5 如果 prop 的值为 undefined、'',那么使用插槽渲染\n const isPropsEmpty = [undefined, ''].includes(propsNode as any);\n if (isPropsEmpty && renderSlot) {\n return handleSlots(instance, name, renderParams);\n }\n // 2.1.6 如果 prop 的值为其他值,那么直接返回\n return propsNode;\n }\n // 2.2 如果未主动传入 prop,那么渲染 slot,当然前提是存在 slot\n if (renderSlot) {\n return handleSlots(instance, name, renderParams);\n }\n // 2.3 如果未主动传入 prop,也没有 slot,那么就走 prop\n const propsNode = instance.props[camelCase(name)] || instance.props[kebabCase(name)];\n if (propsNode === false || propsNode === null) return;\n if (propsNode === true) {\n return defaultNode;\n }\n if (isFunction(propsNode)) return propsNode(h, renderParams);\n return propsNode;\n };\n};\n\n/**\n * 在setup中,通过JSX的方式 TNode,props 和 插槽同时处理。与 renderTNodeJSX 区别在于属性值为 undefined 时会渲染默认节点\n * @example const renderTNodeJSXDefault = useTNodeDefault()\n * @return () => {}\n * @param name 插槽和属性名称\n * @example renderTNodeJSXDefault('closeBtn')\n * @example renderTNodeJSXDefault('closeBtn', <close-icon />) closeBtn 为空时,则兜底渲染 <close-icon />\n * @example renderTNodeJSXDefault('closeBtn', { defaultNode: <close-icon />, params }) 。params 为渲染节点时所需的参数\n */\nexport const useTNodeDefault = () => {\n const renderTNodeJSX = useTNodeJSX();\n return function (name: string, options?: VNode | JSXRenderContext) {\n const defaultNode = getDefaultNode(options);\n return renderTNodeJSX(name, options) || defaultNode;\n };\n};\n\n/**\n * 在setup中,用于处理相同名称的 TNode 渲染\n * @example const renderContent = useContent()\n * @return () => {}\n * @param name1 第一个名称,优先级高于 name2\n * @param name2 第二个名称\n * @param defaultNode 默认渲染内容:当 name1 和 name2 都为空时会启动默认内容渲染\n * @example renderContent('default', 'content')\n * @example renderContent('default', 'content', '我是默认内容')\n * @example renderContent('default', 'content', { defaultNode: '我是默认内容', params })\n */\nexport const useContent = () => {\n const renderTNodeJSX = useTNodeJSX();\n return function (name1: string, name2: string, options?: VNode | JSXRenderContext) {\n // assemble params && defaultNode\n const params = getParams(options);\n const defaultNode = getDefaultNode(options);\n\n const toParams = params ? { params } : undefined;\n\n const node1 = renderTNodeJSX(name1, toParams);\n const node2 = renderTNodeJSX(name2, toParams);\n\n const res = isEmptyNode(node1) ? node2 : node1;\n return isEmptyNode(res) ? defaultNode : res;\n };\n};\n"],"names":["handleSlots","instance","name","params","_instance$slots$camel","_instance$slots","_instance$slots$kebab","_instance$slots2","node","slots","camelCase","call","filter","t","_t$type$toString","_t$type","type","toString","length","kebabCase","_t$type$toString2","_t$type2","isEmptyNode","includes","innerNodes","Array","r","_node2$type","isPropExplicitlySet","propName","vProps","vnode","props","hasOwn","useTNodeJSX","getCurrentInstance","options","renderParams","getParams","defaultNode","getDefaultNode","isSlotFirst","getSlotFirst","renderSlot","_instance$type$props$","propsNode","types","Boolean","Function","isFunction","h","isPropsEmpty","useTNodeDefault","renderTNodeJSX","useContent","name1","name2","toParams","node1","node2","res"],"mappings":"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"}