修复失效的Ref关键字,更新receiver初始化时机为mounted而非setup

This commit is contained in:
陈梓阳 2025-06-04 14:48:36 +08:00
parent 49afb5e3a6
commit 6ed8fd1ddc
6 changed files with 43 additions and 29 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "vue-modpage", "name": "vue-modpage",
"private": true, "private": true,
"version": "1.0.6", "version": "1.0.11",
"type": "module", "type": "module",
"files": [ "files": [
"public", "public",

View File

@ -22,16 +22,16 @@ const dom = ref(h(SlotTester, null, { default: () => [
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
console.log(test.value); console.log(testRef.value);
}, 3000); }, 3000);
}); });
const test = ref<HTMLDivElement>(); const testRef = ref<HTMLDivElement>();
const vueVer = version; const vueVer = version;
const items = [ const items = [
// //
{ {
tag: 'div', data: { ref: test, style: { backgroundColor: 'gray', padding: '10px' } }, children: '1. 字符串渲染测试' tag: 'div', data: { style: { backgroundColor: 'gray', padding: '10px' } }, children: '1. 字符串渲染测试'
}, },
{ {
tag: 'div', data: { style: { background: 'cyan', padding: '10px' } }, children: [ tag: 'div', data: { style: { background: 'cyan', padding: '10px' } }, children: [
@ -65,11 +65,12 @@ const items = [
{ {
tag: 'test-parent', tag: 'test-parent',
data: { data: {
ref: testRef,
message: '8. 事件调用测试', message: '8. 事件调用测试',
style: 'color: red', style: 'color: red',
onCallback: (msg) => { // NativeOn? onCallback: (msg) => { // NativeOn?
alert(msg); alert(msg);
console.log(test.value) console.log(testRef.value)
} }
} }
} }

View File

@ -24,16 +24,17 @@ function splitAttrs(obj: object) : { attrs: Record<string, any>, on: Record<stri
* @returns * @returns
*/ */
function splitVue2Data(rawData?: Record<string, any> | null) { function splitVue2Data(rawData?: Record<string, any> | null) {
// console.warn("Handling Vue2 data: ", rawData); console.log("[ModPage Render Function] Handling Vue2 data: ", rawData);
if (!rawData) return {}; if (!rawData) return null;
if (isVue3) throw new Error("Vue3 data object is not supported in Vue2"); if (isVue3) throw new Error("Vue3 data object is not supported in Vue2");
// Vue2分离式处理 // Vue2分离式处理
else { else {
const on = {}; // 可能需要区分NativeOn const on = {}; // 可能需要区分NativeOn
const { class: cls, style, attrs = {}, props = {}, ...rest } = rawData; // 从 rawData 中显式提取 ref其余的放入 rest
const { class: cls, style, attrs = {}, props = {}, ref: v2Ref, ...rest } = rawData;
// 处理事件 // 处理事件:从 rest 中提取事件处理器到 on 对象
for (const key in rest) { for (const key in rest) {
if (key.indexOf('on') == 0 && key != 'on') { if (key.indexOf('on') == 0 && key != 'on') {
const newKey = key[2].toLowerCase() + key.substring(3); const newKey = key[2].toLowerCase() + key.substring(3);
@ -44,8 +45,10 @@ function splitVue2Data(rawData?: Record<string, any> | null) {
class: cls, class: cls,
style, style,
attrs: attrs, attrs: attrs,
props: { ...props, ...rest }, // 未明确的属性放入props // props 现在由原始 props 和 rest 中剩余的非事件、非 ref 属性组成
props: { ...props, ...rest },
on, on,
ref: v2Ref, // 将提取的 ref 放置在 v2data 的顶层
} }
return v2data; return v2data;
} }
@ -132,5 +135,7 @@ export function hh(tag: string | object, data?: Record<string, any> | null, chil
// console.debug("Processed", { // console.debug("Processed", {
// processedTag, processedData, processedChildren // processedTag, processedData, processedChildren
// }); // });
return render(processedTag, processedData, processedChildren); const result = render(processedTag, processedData, processedChildren);
console.log("[ModPage Render Function] result: ", result);
return result;
} }

View File

@ -2,6 +2,7 @@ import {
defineComponent, defineComponent,
h, h,
isVue2, isVue2,
markRaw,
onMounted, onMounted,
onUnmounted, onUnmounted,
ref, ref,
@ -51,7 +52,9 @@ export default defineComponent({
window[invokerKey][id] = { window[invokerKey][id] = {
getRenderContext, getRenderContext,
initFinish, initFinish,
receiver, getReceiver() {
return receiver;
}
}; };
@ -77,9 +80,11 @@ export default defineComponent({
// vue3 渲染上下文 // vue3 渲染上下文
function getRenderContext() { function getRenderContext() {
return props.items; return markRaw(props.items);
} }
// 用expose外部没有感知用defineExpose在vue2会报错没办法
expose({ expose({
getRefs, getRefs,
getRenderContext, getRenderContext,

View File

@ -31,22 +31,25 @@ export default defineComponent({
const renderItems = ref(invokerContext.getRenderContext() ?? []); const renderItems = ref(invokerContext.getRenderContext() ?? []);
// 若Invoker未接收到当前实例(首次初始化),则进行初始化 // 若Invoker未接收到当前实例(首次初始化),则进行初始化
if (!invokerContext.receiver) { onMounted(function () {
invokerContext.initFinish({ if (!invokerContext.receiver) {
get renderVersion() { invokerContext.initFinish({
return renderVersion.value; get renderVersion() {
}, return renderVersion.value;
Update: function (): void { },
renderVersion.value += 1; Update: function (): void {
renderItems.value = invokerContext.getRenderContext() ?? []; renderVersion.value += 1;
instance?.proxy?.$forceUpdate(); renderItems.value = invokerContext.getRenderContext() ?? [];
}, instance?.proxy?.$forceUpdate();
// @ts-ignore },
get refs() { // @ts-ignore
return instance?.proxy?.$refs; get refs() {
} return instance?.proxy?.$refs;
}); }
} });
}
})
return (createElem) => { return (createElem) => {
const render = isVue2 ? createElem : h; const render = isVue2 ? createElem : h;

Binary file not shown.