@variojs/vue 0.0.1 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -848
- package/dist/bindings.d.ts +2 -1
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js +1 -199
- package/dist/bindings.js.map +1 -1
- package/dist/composable.js +1 -386
- package/dist/features/attrs-builder.d.ts.map +1 -1
- package/dist/features/attrs-builder.js +1 -143
- package/dist/features/attrs-builder.js.map +1 -1
- package/dist/features/children-resolver.js +1 -171
- package/dist/features/component-resolver.js +1 -110
- package/dist/features/computed.js +1 -161
- package/dist/features/event-handler.js +1 -103
- package/dist/features/expression-evaluator.js +1 -28
- package/dist/features/lifecycle-wrapper.js +1 -102
- package/dist/features/loop-handler.js +1 -168
- package/dist/features/path-resolver.d.ts +4 -0
- package/dist/features/path-resolver.d.ts.map +1 -1
- package/dist/features/path-resolver.js +1 -171
- package/dist/features/path-resolver.js.map +1 -1
- package/dist/features/provide-inject.js +1 -139
- package/dist/features/refs.js +1 -113
- package/dist/features/teleport.js +1 -32
- package/dist/features/validators.js +1 -297
- package/dist/features/watch.js +1 -154
- package/dist/index.js +1 -24
- package/dist/renderer.js +1 -244
- package/dist/types.js +0 -16
- package/package.json +18 -5
|
@@ -1,143 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 属性构建模块
|
|
3
|
-
*
|
|
4
|
-
* 负责构建 Vue 组件的属性对象,包括 props、model 绑定、事件等
|
|
5
|
-
*/
|
|
6
|
-
import { createModelBinding } from '../bindings.js';
|
|
7
|
-
/**
|
|
8
|
-
* 属性构建器
|
|
9
|
-
*/
|
|
10
|
-
export class AttrsBuilder {
|
|
11
|
-
getState;
|
|
12
|
-
pathResolver;
|
|
13
|
-
eventHandler;
|
|
14
|
-
staticAttrsCache = new WeakMap();
|
|
15
|
-
constructor(getState, pathResolver, eventHandler) {
|
|
16
|
-
this.getState = getState;
|
|
17
|
-
this.pathResolver = pathResolver;
|
|
18
|
-
this.eventHandler = eventHandler;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* 检查props是否完全静态(不包含表达式)
|
|
22
|
-
*/
|
|
23
|
-
hasStaticProps(schema) {
|
|
24
|
-
if (!schema.props)
|
|
25
|
-
return true;
|
|
26
|
-
for (const value of Object.values(schema.props)) {
|
|
27
|
-
if (typeof value === 'string' && (value.includes('{{') || value.includes('${'))) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
if (typeof value === 'object' && value !== null) {
|
|
31
|
-
// 递归检查嵌套对象
|
|
32
|
-
const nested = value;
|
|
33
|
-
for (const nestedValue of Object.values(nested)) {
|
|
34
|
-
if (typeof nestedValue === 'string' && (nestedValue.includes('{{') || nestedValue.includes('${'))) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* 合并动态属性(model绑定、事件)到静态属性
|
|
44
|
-
*/
|
|
45
|
-
mergeDynamicAttrs(schema, ctx, component, staticAttrs, modelPathStack = []) {
|
|
46
|
-
const attrs = { ...staticAttrs };
|
|
47
|
-
// 仅当 model 为字符串时创建绑定;model 为对象(scope)时不绑定
|
|
48
|
-
const modelPathStr = this.pathResolver.getModelPath(schema.model);
|
|
49
|
-
const shouldBindModel = modelPathStr && typeof schema.model === 'string';
|
|
50
|
-
if (shouldBindModel && modelPathStr) {
|
|
51
|
-
const modelPath = this.pathResolver.resolveModelPath(modelPathStr, schema, ctx, modelPathStack);
|
|
52
|
-
const binding = createModelBinding(schema.type, modelPath, ctx, component, this.getState);
|
|
53
|
-
Object.assign(attrs, binding);
|
|
54
|
-
}
|
|
55
|
-
// 添加具名model绑定
|
|
56
|
-
for (const key in schema) {
|
|
57
|
-
if (key.startsWith('model:')) {
|
|
58
|
-
const modelName = key.slice(6);
|
|
59
|
-
const modelPath = this.pathResolver.resolveModelPath(schema[key], schema, ctx, modelPathStack);
|
|
60
|
-
const binding = createModelBinding(schema.type, modelPath, ctx, component, this.getState, modelName);
|
|
61
|
-
Object.assign(attrs, binding);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// 添加事件处理器
|
|
65
|
-
if (schema.events) {
|
|
66
|
-
const eventHandlers = this.eventHandler.getEventHandlers(schema, ctx);
|
|
67
|
-
Object.assign(attrs, eventHandlers);
|
|
68
|
-
}
|
|
69
|
-
return attrs;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* 构建属性对象
|
|
73
|
-
*
|
|
74
|
-
* 优化策略:
|
|
75
|
-
* - 批量设置属性(减少Object.assign调用)
|
|
76
|
-
* - 静态属性缓存(提升性能)
|
|
77
|
-
* - 事件处理器缓存(避免重复创建)
|
|
78
|
-
*/
|
|
79
|
-
buildAttrs(schema, ctx, component, modelPathStack = [], evalProps) {
|
|
80
|
-
// 检查静态属性缓存(如果props中没有表达式,可以缓存)
|
|
81
|
-
const hasStaticProps = this.hasStaticProps(schema);
|
|
82
|
-
if (hasStaticProps) {
|
|
83
|
-
const cached = this.staticAttrsCache.get(schema);
|
|
84
|
-
if (cached) {
|
|
85
|
-
// 合并动态部分(model绑定、事件)
|
|
86
|
-
return this.mergeDynamicAttrs(schema, ctx, component, cached, modelPathStack);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// 批量构建属性数组,最后一次性合并
|
|
90
|
-
const attrsParts = [];
|
|
91
|
-
// 1. 合并 props(支持表达式插值)
|
|
92
|
-
if (schema.props) {
|
|
93
|
-
attrsParts.push(evalProps(schema.props, ctx));
|
|
94
|
-
}
|
|
95
|
-
// 2. 处理双向绑定(支持多 model)。仅当 model 为字符串时创建绑定
|
|
96
|
-
const modelPathStr = this.pathResolver.getModelPath(schema.model);
|
|
97
|
-
const shouldBindModel = modelPathStr && typeof schema.model === 'string';
|
|
98
|
-
if (shouldBindModel && modelPathStr) {
|
|
99
|
-
const modelPath = this.pathResolver.resolveModelPath(modelPathStr, schema, ctx, modelPathStack);
|
|
100
|
-
const binding = createModelBinding(schema.type, modelPath, ctx, component, this.getState);
|
|
101
|
-
attrsParts.push(binding);
|
|
102
|
-
}
|
|
103
|
-
// 处理具名 model(model:xxx)
|
|
104
|
-
for (const key in schema) {
|
|
105
|
-
if (key.startsWith('model:')) {
|
|
106
|
-
const modelName = key.slice(6); // 移除 'model:' 前缀
|
|
107
|
-
const modelPath = this.pathResolver.resolveModelPath(schema[key], schema, ctx, modelPathStack);
|
|
108
|
-
const binding = createModelBinding(schema.type, modelPath, ctx, component, this.getState, modelName);
|
|
109
|
-
attrsParts.push(binding);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// 3. 处理事件(使用缓存)
|
|
113
|
-
if (schema.events) {
|
|
114
|
-
const eventHandlers = this.eventHandler.getEventHandlers(schema, ctx);
|
|
115
|
-
attrsParts.push(eventHandlers);
|
|
116
|
-
}
|
|
117
|
-
// 批量合并所有属性
|
|
118
|
-
const attrs = Object.assign({}, ...attrsParts);
|
|
119
|
-
// 4. 统一处理 style 格式(确保始终是对象)
|
|
120
|
-
if (attrs.style) {
|
|
121
|
-
if (typeof attrs.style === 'string') {
|
|
122
|
-
const styleObj = {};
|
|
123
|
-
attrs.style.split(';').forEach((rule) => {
|
|
124
|
-
const [key, value] = rule.split(':').map((s) => s.trim());
|
|
125
|
-
if (key && value) {
|
|
126
|
-
const camelKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
127
|
-
styleObj[camelKey] = value;
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
attrs.style = styleObj;
|
|
131
|
-
}
|
|
132
|
-
else if (Array.isArray(attrs.style)) {
|
|
133
|
-
attrs.style = {};
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// 缓存静态属性
|
|
137
|
-
if (hasStaticProps) {
|
|
138
|
-
this.staticAttrsCache.set(schema, { ...attrs });
|
|
139
|
-
}
|
|
140
|
-
return attrs;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
//# sourceMappingURL=attrs-builder.js.map
|
|
1
|
+
import{createModelBinding as g}from"../bindings.js";class j{getState;pathResolver;eventHandler;staticAttrsCache=new WeakMap;constructor(t,e,l){this.getState=t,this.pathResolver=e,this.eventHandler=l}hasStaticProps(t){if(!t.props)return!0;for(const e of Object.values(t.props)){if(typeof e=="string"&&(e.includes("{{")||e.includes("${")))return!1;if(typeof e=="object"&&e!==null){const l=e;for(const n of Object.values(l))if(typeof n=="string"&&(n.includes("{{")||n.includes("${")))return!1}}return!0}mergeDynamicAttrs(t,e,l,n,u=[]){const d={...n},i=this.pathResolver.getModelPath(t.model),f=typeof t.model=="object"&&t.model!==null&&t.model.scope===!0;if(!!i&&!f&&i){const r=this.pathResolver.resolveModelPath(i,t,e,u),o=this.pathResolver.getModelDefault(t.model),s=g(t.type,r,e,l,this.getState,void 0,o);Object.assign(d,s)}for(const r in t)if(r.startsWith("model:")){const o=r.slice(6),s=this.pathResolver.resolveModelPath(t[r],t,e,u),a=g(t.type,s,e,l,this.getState,o);Object.assign(d,a)}if(t.events){const r=this.eventHandler.getEventHandlers(t,e);Object.assign(d,r)}return d}buildAttrs(t,e,l,n=[],u){const d=this.hasStaticProps(t);if(d){const s=this.staticAttrsCache.get(t);if(s)return this.mergeDynamicAttrs(t,e,l,s,n)}const i=[];t.props&&i.push(u(t.props,e));const f=this.pathResolver.getModelPath(t.model),c=typeof t.model=="object"&&t.model!==null&&t.model.scope===!0;if(!!f&&!c&&f){const s=this.pathResolver.resolveModelPath(f,t,e,n),a=this.pathResolver.getModelDefault(t.model),p=g(t.type,s,e,l,this.getState,void 0,a);i.push(p)}for(const s in t)if(s.startsWith("model:")){const a=s.slice(6),p=this.pathResolver.resolveModelPath(t[s],t,e,n),h=g(t.type,p,e,l,this.getState,a);i.push(h)}if(t.events){const s=this.eventHandler.getEventHandlers(t,e);i.push(s)}const o=Object.assign({},...i);if(o.style)if(typeof o.style=="string"){const s={};o.style.split(";").forEach(a=>{const[p,h]=a.split(":").map(v=>v.trim());if(p&&h){const v=p.replace(/-([a-z])/g,(M,y)=>y.toUpperCase());s[v]=h}}),o.style=s}else Array.isArray(o.style)&&(o.style={});return d&&this.staticAttrsCache.set(t,{...o}),o}}export{j as AttrsBuilder};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attrs-builder.js","sourceRoot":"","sources":["../../src/features/attrs-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAInD;;GAEG;AACH,MAAM,OAAO,YAAY;IAIb;IACA;IACA;IALF,gBAAgB,GAAG,IAAI,OAAO,EAAmC,CAAA;IAEzE,YACU,QAAiC,EACjC,YAA+B,EAC/B,YAA0B;QAF1B,aAAQ,GAAR,QAAQ,CAAyB;QACjC,iBAAY,GAAZ,YAAY,CAAmB;QAC/B,iBAAY,GAAZ,YAAY,CAAc;IACjC,CAAC;IAEJ;;OAEG;IACH,cAAc,CAAC,MAAkB;QAC/B,IAAI,CAAC,MAAM,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QAE9B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAChF,OAAO,KAAK,CAAA;YACd,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBAChD,WAAW;gBACX,MAAM,MAAM,GAAG,KAAgC,CAAA;gBAC/C,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBAChD,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;wBAClG,OAAO,KAAK,CAAA;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;OAEG;IACH,iBAAiB,CACf,MAAkB,EAClB,GAAmB,EACnB,SAAc,EACd,WAAgC,EAChC,iBAAgC,EAAE;QAElC,MAAM,KAAK,GAAG,EAAE,GAAG,WAAW,EAAE,CAAA;QAEhC,
|
|
1
|
+
{"version":3,"file":"attrs-builder.js","sourceRoot":"","sources":["../../src/features/attrs-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,171 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 子节点处理模块
|
|
3
|
-
*
|
|
4
|
-
* 负责解析 Schema 的子节点,包括作用域插槽和文本内容
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* 子节点解析器
|
|
8
|
-
*/
|
|
9
|
-
export class ChildrenResolver {
|
|
10
|
-
createVNode;
|
|
11
|
-
expressionEvaluator;
|
|
12
|
-
constructor(createVNode, expressionEvaluator) {
|
|
13
|
-
this.createVNode = createVNode;
|
|
14
|
-
this.expressionEvaluator = expressionEvaluator;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* 解析子节点
|
|
18
|
-
* 支持插槽(template 节点)和作用域插槽
|
|
19
|
-
*/
|
|
20
|
-
resolveChildren(schema, ctx, modelPathStack = []) {
|
|
21
|
-
const children = schema.children;
|
|
22
|
-
if (!children) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
// 字符串子节点(支持表达式插值)
|
|
26
|
-
if (typeof children === 'string') {
|
|
27
|
-
return this.resolveTextContent(children, ctx);
|
|
28
|
-
}
|
|
29
|
-
// 检查是否有插槽(template 节点带 slot 属性)
|
|
30
|
-
const hasSlots = children.some((child) => child.type === 'template' && child.slot);
|
|
31
|
-
if (hasSlots) {
|
|
32
|
-
// 处理插槽(包括作用域插槽和普通插槽)
|
|
33
|
-
return this.resolveSlots(children, ctx, modelPathStack);
|
|
34
|
-
}
|
|
35
|
-
// 数组子节点 - 过滤掉 null/undefined,确保返回有效的 VNode 数组
|
|
36
|
-
const vnodes = children
|
|
37
|
-
.map((child) => {
|
|
38
|
-
try {
|
|
39
|
-
return this.createVNode(child, ctx, modelPathStack);
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
.filter((vnode) => vnode !== null && vnode !== undefined);
|
|
46
|
-
// 如果所有子节点都无效,返回 null
|
|
47
|
-
return vnodes.length > 0 ? vnodes : null;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* 解析插槽(包括作用域插槽和普通插槽)
|
|
51
|
-
* 将 template 节点转换为 Vue 3 的插槽函数
|
|
52
|
-
*/
|
|
53
|
-
resolveSlots(children, ctx, modelPathStack = []) {
|
|
54
|
-
const slots = {};
|
|
55
|
-
const regularChildren = [];
|
|
56
|
-
children.forEach((child) => {
|
|
57
|
-
if (child.type === 'template' && child.slot) {
|
|
58
|
-
const template = child;
|
|
59
|
-
const slotName = template.slot;
|
|
60
|
-
const scopeVarName = template.props?.scope;
|
|
61
|
-
const isScoped = !!scopeVarName;
|
|
62
|
-
// 创建插槽函数
|
|
63
|
-
slots[slotName] = (scope) => {
|
|
64
|
-
// 创建上下文:作用域插槽需要添加 scope 变量
|
|
65
|
-
let slotCtx = ctx;
|
|
66
|
-
if (isScoped && scope !== undefined) {
|
|
67
|
-
slotCtx = Object.create(ctx);
|
|
68
|
-
slotCtx[scopeVarName] = scope;
|
|
69
|
-
}
|
|
70
|
-
// 解析子节点
|
|
71
|
-
if (typeof template.children === 'string') {
|
|
72
|
-
return this.resolveTextContent(template.children, slotCtx);
|
|
73
|
-
}
|
|
74
|
-
else if (Array.isArray(template.children)) {
|
|
75
|
-
return template.children
|
|
76
|
-
.map((c) => {
|
|
77
|
-
try {
|
|
78
|
-
return this.createVNode(c, slotCtx, modelPathStack);
|
|
79
|
-
}
|
|
80
|
-
catch (error) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
.filter((v) => v !== null && v !== undefined);
|
|
85
|
-
}
|
|
86
|
-
return null;
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
// 非 template 节点,收集到 regularChildren
|
|
91
|
-
try {
|
|
92
|
-
const vnode = this.createVNode(child, ctx, modelPathStack);
|
|
93
|
-
if (vnode) {
|
|
94
|
-
regularChildren.push(vnode);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
// 忽略错误
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
// 如果有普通子节点,添加到 default 插槽
|
|
103
|
-
if (regularChildren.length > 0) {
|
|
104
|
-
if (!slots.default) {
|
|
105
|
-
slots.default = () => regularChildren;
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
const existingDefault = slots.default;
|
|
109
|
-
slots.default = (scope) => {
|
|
110
|
-
const scoped = existingDefault(scope);
|
|
111
|
-
return Array.isArray(scoped) ? [...scoped, ...regularChildren] : regularChildren;
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return slots;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* 解析文本内容(支持表达式插值)
|
|
119
|
-
*/
|
|
120
|
-
resolveTextContent(text, ctx) {
|
|
121
|
-
// 匹配 {{ expression }} 模式
|
|
122
|
-
const exprPattern = /\{\{\s*([^}]+)\s*\}\}/g;
|
|
123
|
-
return text.replace(exprPattern, (match, expr) => {
|
|
124
|
-
try {
|
|
125
|
-
const trimmedExpr = expr.trim();
|
|
126
|
-
const value = this.expressionEvaluator.evaluateExpr(trimmedExpr, ctx);
|
|
127
|
-
return value != null ? String(value) : '';
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
console.warn('[Expression Error]', expr, error);
|
|
131
|
-
return match;
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* 求值 props(支持表达式插值)
|
|
137
|
-
*/
|
|
138
|
-
evalProps(props, ctx) {
|
|
139
|
-
const result = {};
|
|
140
|
-
Object.entries(props).forEach(([key, value]) => {
|
|
141
|
-
if (typeof value === 'string') {
|
|
142
|
-
// 检查是否为表达式插值
|
|
143
|
-
if (value.startsWith('{{') && value.endsWith('}}')) {
|
|
144
|
-
const expr = value.slice(2, -2).trim();
|
|
145
|
-
result[key] = this.expressionEvaluator.evaluateExpr(expr, ctx);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
// 普通字符串,检查是否包含表达式插值
|
|
149
|
-
result[key] = this.resolveTextContent(value, ctx);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
else if (typeof value === 'object' && value !== null) {
|
|
153
|
-
// 嵌套对象(递归处理)
|
|
154
|
-
if (Array.isArray(value)) {
|
|
155
|
-
result[key] = value.map((item) => typeof item === 'string'
|
|
156
|
-
? this.resolveTextContent(item, ctx)
|
|
157
|
-
: this.evalProps(item, ctx));
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
result[key] = this.evalProps(value, ctx);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
// 静态值
|
|
165
|
-
result[key] = value;
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
return result;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
//# sourceMappingURL=children-resolver.js.map
|
|
1
|
+
class y{createVNode;expressionEvaluator;constructor(l,n){this.createVNode=l,this.expressionEvaluator=n}resolveChildren(l,n,o=[]){const r=l.children;if(!r)return null;if(typeof r=="string")return this.resolveTextContent(r,n);if(r.some(e=>e.type==="template"&&e.slot))return this.resolveSlots(r,n,o);const s=r.map(e=>{try{return this.createVNode(e,n,o)}catch{return null}}).filter(e=>e!=null);return s.length>0?s:null}resolveSlots(l,n,o=[]){const r={},t=[];if(l.forEach(s=>{if(s.type==="template"&&s.slot){const e=s,i=e.slot,u=e.props?.scope,f=!!u;r[i]=p=>{let a=n;return f&&p!==void 0&&(a=Object.create(n),a[u]=p),typeof e.children=="string"?this.resolveTextContent(e.children,a):Array.isArray(e.children)?e.children.map(c=>{try{return this.createVNode(c,a,o)}catch{return null}}).filter(c=>c!=null):null}}else try{const e=this.createVNode(s,n,o);e&&t.push(e)}catch{}}),t.length>0)if(!r.default)r.default=()=>t;else{const s=r.default;r.default=e=>{const i=s(e);return Array.isArray(i)?[...i,...t]:t}}return r}resolveTextContent(l,n){const o=/\{\{\s*([^}]+)\s*\}\}/g;return l.replace(o,(r,t)=>{try{const s=t.trim(),e=this.expressionEvaluator.evaluateExpr(s,n);return e!=null?String(e):""}catch(s){return console.warn("[Expression Error]",t,s),r}})}evalProps(l,n){const o={};return Object.entries(l).forEach(([r,t])=>{if(typeof t=="string")if(t.startsWith("{{")&&t.endsWith("}}")){const s=t.slice(2,-2).trim();o[r]=this.expressionEvaluator.evaluateExpr(s,n)}else o[r]=this.resolveTextContent(t,n);else typeof t=="object"&&t!==null?Array.isArray(t)?o[r]=t.map(s=>typeof s=="string"?this.resolveTextContent(s,n):this.evalProps(s,n)):o[r]=this.evalProps(t,n):o[r]=t}),o}}export{y as ChildrenResolver};
|
|
@@ -1,110 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 组件解析模块
|
|
3
|
-
*
|
|
4
|
-
* 负责解析 Schema 中的组件类型,支持原生 DOM 元素和全局注册的组件
|
|
5
|
-
*/
|
|
6
|
-
import { markRaw } from 'vue';
|
|
7
|
-
/**
|
|
8
|
-
* 原生 HTML DOM 元素列表
|
|
9
|
-
* 用于快速判断是否为原生元素,避免不必要的组件解析
|
|
10
|
-
*/
|
|
11
|
-
const NATIVE_DOM_ELEMENTS = new Set([
|
|
12
|
-
// 文档结构
|
|
13
|
-
'html', 'head', 'body', 'div', 'span', 'p', 'section', 'article', 'aside', 'nav', 'header', 'footer', 'main',
|
|
14
|
-
// 文本内容
|
|
15
|
-
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote', 'pre', 'code', 'em', 'strong', 'small', 'sub', 'sup',
|
|
16
|
-
'mark', 'del', 'ins', 'abbr', 'dfn', 'cite', 'q', 'samp', 'kbd', 'var', 'time', 'b', 'i', 'u', 's', 'wbr',
|
|
17
|
-
// 列表
|
|
18
|
-
'ul', 'ol', 'li', 'dl', 'dt', 'dd',
|
|
19
|
-
// 表格
|
|
20
|
-
'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'caption', 'colgroup', 'col',
|
|
21
|
-
// 表单
|
|
22
|
-
'form', 'input', 'textarea', 'select', 'option', 'optgroup', 'button', 'label', 'fieldset', 'legend',
|
|
23
|
-
'datalist', 'output', 'progress', 'meter',
|
|
24
|
-
// 媒体
|
|
25
|
-
'img', 'picture', 'source', 'audio', 'video', 'track', 'canvas', 'svg', 'math',
|
|
26
|
-
// 链接
|
|
27
|
-
'a', 'area', 'link', 'base',
|
|
28
|
-
// 元数据
|
|
29
|
-
'meta', 'title', 'style', 'script', 'noscript',
|
|
30
|
-
// 嵌入内容
|
|
31
|
-
'iframe', 'embed', 'object', 'param',
|
|
32
|
-
// 其他
|
|
33
|
-
'br', 'hr', 'template', 'slot', 'details', 'summary', 'dialog'
|
|
34
|
-
]);
|
|
35
|
-
/**
|
|
36
|
-
* 判断是否为原生 DOM 元素
|
|
37
|
-
*/
|
|
38
|
-
function isNativeDOMElement(type) {
|
|
39
|
-
return NATIVE_DOM_ELEMENTS.has(type.toLowerCase());
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* 组件解析器
|
|
43
|
-
*/
|
|
44
|
-
export class ComponentResolver {
|
|
45
|
-
componentCache = new Map();
|
|
46
|
-
globalComponents = null;
|
|
47
|
-
constructor(globalComponents = null) {
|
|
48
|
-
this.globalComponents = globalComponents;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* 解析组件
|
|
52
|
-
* 自动解析全局注册的组件(通过 app.component() 注册的所有组件)
|
|
53
|
-
* 不针对任何特定的组件库,完全依赖 Vue 的全局组件注册机制
|
|
54
|
-
*
|
|
55
|
-
* 使用缓存提升性能
|
|
56
|
-
*/
|
|
57
|
-
resolveComponent(type) {
|
|
58
|
-
// 检查缓存
|
|
59
|
-
if (this.componentCache.has(type)) {
|
|
60
|
-
return this.componentCache.get(type);
|
|
61
|
-
}
|
|
62
|
-
let resolved = null;
|
|
63
|
-
// 如果是原生 DOM 元素,直接返回类型名(Vue 的 h 函数会将其作为 HTML 标签处理)
|
|
64
|
-
if (isNativeDOMElement(type)) {
|
|
65
|
-
resolved = type;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
try {
|
|
69
|
-
// 从全局组件注册表中查找组件
|
|
70
|
-
// 支持所有通过 app.component() 注册的全局组件(包括 Element Plus、自定义组件等)
|
|
71
|
-
if (this.globalComponents) {
|
|
72
|
-
const globalComponent = this.globalComponents[type];
|
|
73
|
-
if (globalComponent) {
|
|
74
|
-
resolved = globalComponent;
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
// 组件未找到,作为 HTML 标签使用(可能是未知的原生元素或自定义标签)
|
|
78
|
-
resolved = type;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
resolved = type;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
// 解析失败,作为 HTML 标签使用
|
|
87
|
-
resolved = type;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// 缓存结果(包括原生元素和字符串类型,避免重复解析)
|
|
91
|
-
// 对于组件对象(非字符串),使用 markRaw 标记,避免被响应式处理
|
|
92
|
-
const cachedComponent = typeof resolved === 'string' ? resolved : markRaw(resolved);
|
|
93
|
-
this.componentCache.set(type, cachedComponent);
|
|
94
|
-
return cachedComponent;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* 清除组件解析缓存
|
|
98
|
-
* 用于组件注册变更后的缓存失效
|
|
99
|
-
*/
|
|
100
|
-
clearComponentCache() {
|
|
101
|
-
this.componentCache.clear();
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* 使特定组件的缓存失效
|
|
105
|
-
*/
|
|
106
|
-
invalidateComponentCache(type) {
|
|
107
|
-
this.componentCache.delete(type);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=component-resolver.js.map
|
|
1
|
+
import{markRaw as l}from"vue";const s=new Set(["html","head","body","div","span","p","section","article","aside","nav","header","footer","main","h1","h2","h3","h4","h5","h6","p","blockquote","pre","code","em","strong","small","sub","sup","mark","del","ins","abbr","dfn","cite","q","samp","kbd","var","time","b","i","u","s","wbr","ul","ol","li","dl","dt","dd","table","thead","tbody","tfoot","tr","th","td","caption","colgroup","col","form","input","textarea","select","option","optgroup","button","label","fieldset","legend","datalist","output","progress","meter","img","picture","source","audio","video","track","canvas","svg","math","a","area","link","base","meta","title","style","script","noscript","iframe","embed","object","param","br","hr","template","slot","details","summary","dialog"]);function r(a){return s.has(a.toLowerCase())}class c{componentCache=new Map;globalComponents=null;constructor(e=null){this.globalComponents=e}resolveComponent(e){if(this.componentCache.has(e))return this.componentCache.get(e);let t=null;if(r(e))t=e;else try{if(this.globalComponents){const o=this.globalComponents[e];o?t=o:t=e}else t=e}catch{t=e}const n=typeof t=="string"?t:l(t);return this.componentCache.set(e,n),n}clearComponentCache(){this.componentCache.clear()}invalidateComponentCache(e){this.componentCache.delete(e)}}export{c as ComponentResolver};
|
|
@@ -1,161 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Computed 支持
|
|
3
|
-
*
|
|
4
|
-
* 在 Schema 节点上支持计算属性,使用表达式字符串
|
|
5
|
-
*
|
|
6
|
-
* 特性:
|
|
7
|
-
* - 精细化依赖追踪:只追踪表达式中使用的状态路径
|
|
8
|
-
* - 缓存机制:相同 schema 节点复用 computed 实例
|
|
9
|
-
* - 自动清理:组件卸载时清理缓存
|
|
10
|
-
*/
|
|
11
|
-
import { computed, onUnmounted, getCurrentInstance } from 'vue';
|
|
12
|
-
import { evaluate, parseExpression, extractDependencies } from '@vario/core';
|
|
13
|
-
/**
|
|
14
|
-
* Computed 缓存管理器
|
|
15
|
-
* 使用 WeakMap 以 schema 为 key,避免内存泄漏
|
|
16
|
-
*/
|
|
17
|
-
const computedCache = new WeakMap();
|
|
18
|
-
/**
|
|
19
|
-
* 从表达式中提取依赖的状态路径
|
|
20
|
-
*
|
|
21
|
-
* @param expr 表达式字符串
|
|
22
|
-
* @returns 依赖路径数组
|
|
23
|
-
*/
|
|
24
|
-
function extractExprDependencies(expr) {
|
|
25
|
-
try {
|
|
26
|
-
const ast = parseExpression(expr);
|
|
27
|
-
return extractDependencies(ast);
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
// 解析失败时返回空数组,使用粗粒度追踪
|
|
31
|
-
return [];
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* 根据依赖路径从响应式状态中读取值(触发依赖追踪)
|
|
36
|
-
*
|
|
37
|
-
* @param state 响应式状态对象
|
|
38
|
-
* @param deps 依赖路径数组
|
|
39
|
-
*/
|
|
40
|
-
function trackDependencies(state, deps) {
|
|
41
|
-
if (!state || deps.length === 0)
|
|
42
|
-
return;
|
|
43
|
-
for (const dep of deps) {
|
|
44
|
-
// 处理通配符依赖:items.* -> 访问整个数组
|
|
45
|
-
if (dep.endsWith('.*')) {
|
|
46
|
-
const basePath = dep.slice(0, -2);
|
|
47
|
-
const value = getNestedValue(state, basePath);
|
|
48
|
-
// 触发数组/对象的追踪
|
|
49
|
-
if (Array.isArray(value)) {
|
|
50
|
-
void value.length;
|
|
51
|
-
}
|
|
52
|
-
else if (value && typeof value === 'object') {
|
|
53
|
-
void Object.keys(value);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
else if (dep.includes('.')) {
|
|
57
|
-
// 嵌套路径:user.name
|
|
58
|
-
void getNestedValue(state, dep);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
// 顶级路径
|
|
62
|
-
void state[dep];
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* 获取嵌套路径的值
|
|
68
|
-
*/
|
|
69
|
-
function getNestedValue(obj, path) {
|
|
70
|
-
const parts = path.split('.');
|
|
71
|
-
let current = obj;
|
|
72
|
-
for (const part of parts) {
|
|
73
|
-
if (current == null)
|
|
74
|
-
return undefined;
|
|
75
|
-
current = current[part];
|
|
76
|
-
}
|
|
77
|
-
return current;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* 为 Schema 节点创建计算属性
|
|
81
|
-
*
|
|
82
|
-
* @param schema Schema 节点
|
|
83
|
-
* @param ctx 运行时上下文
|
|
84
|
-
* @param getState 获取响应式状态的函数
|
|
85
|
-
* @param useCache 是否使用缓存(默认 true)
|
|
86
|
-
*/
|
|
87
|
-
export function createComputedProps(schema, ctx, getState, useCache = true) {
|
|
88
|
-
if (!schema.computed || Object.keys(schema.computed).length === 0) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
// 尝试从缓存获取
|
|
92
|
-
if (useCache) {
|
|
93
|
-
const cached = computedCache.get(schema);
|
|
94
|
-
if (cached) {
|
|
95
|
-
return cached;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const computedProps = {};
|
|
99
|
-
// 预先解析所有表达式的依赖
|
|
100
|
-
const depsMap = new Map();
|
|
101
|
-
for (const [key, expr] of Object.entries(schema.computed)) {
|
|
102
|
-
depsMap.set(key, extractExprDependencies(expr));
|
|
103
|
-
}
|
|
104
|
-
for (const [key, expr] of Object.entries(schema.computed)) {
|
|
105
|
-
const deps = depsMap.get(key) || [];
|
|
106
|
-
computedProps[key] = computed(() => {
|
|
107
|
-
try {
|
|
108
|
-
// 精细化依赖追踪
|
|
109
|
-
if (getState) {
|
|
110
|
-
const state = getState();
|
|
111
|
-
trackDependencies(state, deps);
|
|
112
|
-
}
|
|
113
|
-
return evaluate(expr, ctx);
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
console.warn(`[Vario] Computed property "${key}" evaluation error:`, error);
|
|
117
|
-
return undefined;
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
// 缓存结果
|
|
122
|
-
if (useCache) {
|
|
123
|
-
computedCache.set(schema, computedProps);
|
|
124
|
-
// 如果在组件上下文中,注册清理
|
|
125
|
-
const instance = getCurrentInstance();
|
|
126
|
-
if (instance) {
|
|
127
|
-
onUnmounted(() => {
|
|
128
|
-
computedCache.delete(schema);
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return computedProps;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* 将计算属性合并到 props 中
|
|
136
|
-
*/
|
|
137
|
-
export function mergeComputedProps(props, computedProps) {
|
|
138
|
-
if (!computedProps) {
|
|
139
|
-
return props;
|
|
140
|
-
}
|
|
141
|
-
const result = { ...props };
|
|
142
|
-
for (const [key, computedRef] of Object.entries(computedProps)) {
|
|
143
|
-
// 计算属性优先级高于原有 props
|
|
144
|
-
result[key] = computedRef.value;
|
|
145
|
-
}
|
|
146
|
-
return result;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* 清除指定 schema 的 computed 缓存
|
|
150
|
-
*/
|
|
151
|
-
export function clearComputedCache(schema) {
|
|
152
|
-
return computedCache.delete(schema);
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* 清除所有 computed 缓存(用于测试或热重载)
|
|
156
|
-
*/
|
|
157
|
-
export function clearAllComputedCache() {
|
|
158
|
-
// WeakMap 无法遍历,只能通过引用删除
|
|
159
|
-
// 这个函数主要用于标记意图,实际清理依赖 WeakMap 的 GC
|
|
160
|
-
}
|
|
161
|
-
//# sourceMappingURL=computed.js.map
|
|
1
|
+
import{computed as l,onUnmounted as d,getCurrentInstance as m}from"vue";import{evaluate as h,parseExpression as y,extractDependencies as C}from"@vario/core";const s=new WeakMap;function g(t){try{const o=y(t);return C(o)}catch{return[]}}function b(t,o){if(!(!t||o.length===0))for(const e of o)if(e.endsWith(".*")){const r=e.slice(0,-2),n=f(t,r);Array.isArray(n)?n.length:n&&typeof n=="object"&&Object.keys(n)}else e.includes(".")?f(t,e):t[e]}function f(t,o){const e=o.split(".");let r=t;for(const n of e){if(r==null)return;r=r[n]}return r}function j(t,o,e,r=!0){if(!t.computed||Object.keys(t.computed).length===0)return null;if(r){const c=s.get(t);if(c)return c}const n={},i=new Map;for(const[c,u]of Object.entries(t.computed))i.set(c,g(u));for(const[c,u]of Object.entries(t.computed)){const p=i.get(c)||[];n[c]=l(()=>{try{if(e){const a=e();b(a,p)}return h(u,o)}catch(a){console.warn(`[Vario] Computed property "${c}" evaluation error:`,a);return}})}return r&&(s.set(t,n),m()&&d(()=>{s.delete(t)})),n}function O(t,o){if(!o)return t;const e={...t};for(const[r,n]of Object.entries(o))e[r]=n.value;return e}function v(t){return s.delete(t)}function w(){}export{w as clearAllComputedCache,v as clearComputedCache,j as createComputedProps,O as mergeComputedProps};
|