Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

自定义的widget是否能通过调用js得到想要的Widget #1399

Open
zjt123 opened this issue May 13, 2022 · 8 comments
Open

自定义的widget是否能通过调用js得到想要的Widget #1399

zjt123 opened this issue May 13, 2022 · 8 comments
Assignees
Labels
enhancement New feature or request

Comments

@zjt123
Copy link

zjt123 commented May 13, 2022

使用场景 | Use case

自定义的widget是否能通过调用js得到想要的Widget, 目前看文档dart和js通讯好像做不到类似的
例如自定义了一个 widget, widget里面对业务逻辑的处理,但是ui需要通过调用js得到的,js根据业务数据来生成对应的ui a、b、c..等

提案 | Proposal

伪代码例子:

Kraken.defineCustomElement('k-demo-element2',
    (context) {
  return DemoElement2(context);
});

class DemoElement2 extends WidgetElement {
List dataList = [{"name":"1", "style":"1"}, {"name":"2", "style":"2"}, {"name":"3", "style":"3"}];

DemoElement2(context) : super(context, defaultStyle: {'display': 'block'});
@OverRide
Widget build(BuildContext context, Map<String, dynamic> properties,
List children) {
return Container(
color: Colors.blue,
width: 300,
height: 500,
child:CustomScrollView(
slivers: [SliverList(
delegate: SliverChildBuilderDelegate(
(_, index) => _ListWidget(index),
childCount: dataList.length,
)])); }

_ListWidget(index) {
// dataList[index] , 根据数据调用js,能否得到一个StyleWidget ???
return StyleWidget;
}
dynamic sayHi(List args) {
print(args);
print(args[0]);
print(args[0].runtimeType);
}

@OverRide
getBindingProperty(String key) {
if (key == 'sayHi') {
return sayHi;
}

return super.getBindingProperty(key);

}
}

@zjt123 zjt123 added the enhancement New feature or request label May 13, 2022
@answershuto
Copy link
Member

用 JS 就是通过 document.createElement 创建一个新的 custom element。

@zjt123
Copy link
Author

zjt123 commented May 13, 2022

用 JS 就是通过 document.createElement 创建一个新的 custom element。

那怎么返回给这个WidgetElement呢? appendChild?

@answershuto
Copy link
Member

嗯, appendChild 后,子 Element 会传递到 WidgetElement 的 build 中,chidren 参数会带上。

@zjt123
Copy link
Author

zjt123 commented May 13, 2022

嗯, appendChild 后,子 Element 会传递到 WidgetElement 的 build 中,chidren 参数会带上。

我现在是这么弄的,但是把childen放到列表里面就会有问题,滚动也有问题,感觉自定义的WidgetElement列表和KrakenElementToWidgetAdaptor不兼容。可以看我给出来的代码. 能力有限,尝试改源码滚动的时候也会报错。动态增加flutter创建出来的元素(append1替换成append2方法)是没问题的。

js代码:

    const container = document.createElement('div');
    // 必须指定渲染容器节点滚动方向的尺寸(height).
    container.style.height = '100vh';
    const outter = document.createElement('k-demo-element2');
    container.appendChild(outter);
    const ele = document.createElement('div');
    ele.style.height = '100';
    const clickUi = document.createTextNode(`测试点击`);
    ele.appendChild(clickUi);
    container.appendChild(ele);

    ele.addEventListener('click', function() {
      const tmpdiv = document.createElement('div');
      tmpdiv.style.height = '200px';
      tmpdiv.style.width = '100px';
      tmpdiv.appendChild(document.createTextNode(`第 1个元素`));
      outter.appendChild(tmpdiv);
      // outter.sayHi(tmpdiv); // flutter: Kraken: Hi!
    });
    document.body.appendChild(container);

dart代码:

import 'package:kraken/widget.dart';
import 'package:flutter/material.dart';

class DemoElement2 extends WidgetElement {
List goodsList = [];
late Widget targetW;
bool isInit = false;

// DemoElement2(context) : super(context, defaultStyle: {'display': 'block'});
DemoElement2(context) : super(context);

append1(children) {
goodsList[0].appendW(children);
}

append2() {
goodsList[0].appendW([Container(
height: 100,
width: 111,
child: Text("1111"),)]);
}

@OverRide
Widget build(BuildContext context, Map<String, dynamic> properties,
List children) {
// setAttribute("id", "test1");
if (children.length > 0) {
append1(children);
// TODO append2是没问题的。
// append2()
}
if (isInit) {
return targetW;
}
isInit = true;
goodsList.add(MyList());
targetW = Container(
color: Colors.blue,
width: 300,
height: 500,
child:CustomScrollView(
slivers: goodsList,));
return targetW;
}

dynamic sayHi(List args) {
print(args);
print(args[0]);
print(args[0].runtimeType);
}

@OverRide
getBindingProperty(String key) {
if (key == 'sayHi') {
return sayHi;
}

return super.getBindingProperty(key);

}
}
class MyList extends StatefulWidget {

List wList = [];
_MyListState state = _MyListState();
@OverRide
State createState() {
return state;
}

appendW(List w) {
for (Widget w in wList) {
KrakenElementToWidgetAdaptor renderObjectWidget = w as KrakenElementToWidgetAdaptor;
// renderObjectWidget.check1();
// TODO 尝试在KrakenElementToWidgetAdaptor增加check1方法,调用detachRenderObject,并且相关的super.mount 和 super.unmount 加上try catch ,能解决每次add元素的child.parend != null
// void check1() {
// bool isRendererAttached = _krakenNode.isRendererAttached;
// print(' isRendererAttached: ${isRendererAttached}');
// // print('zjt isConnected: ${_krakenNode.isConnected}');
// if (isRendererAttached) {
// _krakenNode.flutterElement?.detachRenderObject();
// }
// }
}
wList.addAll(w);
state.setState(() {

});

}
}
class MyListState extends State {
@OverRide
Widget build(BuildContext context) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(
, index) => _ListWidget(index),
childCount: widget.wList.length,
)
);
}

_ListWidget(index) {
KrakenElementToWidgetAdaptor renderObjectWidget = widget.wList[index] as KrakenElementToWidgetAdaptor;
return Container(child: renderObjectWidget);
}
}

异常信息:

======== Exception caught by widgets library =======================================================
The following assertion was thrown building Container:
'package:flutter/src/foundation/node.dart': Failed assertion: line 128 pos 12: 'child._parent == null': is not true.

Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=2_bug.md

The relevant error-causing widget was:
Container Container:file:///Users/apple/job/app/lib/nflutter_components/demo_compont/views/demo_component2.dart:107:12
When the exception was thrown, this was the stack:
#2 AbstractNode.adoptChild (package:flutter/src/foundation/node.dart:128:12)
#3 RenderObject.adoptChild (package:flutter/src/rendering/object.dart:1331:11)
#4 ContainerRenderObjectMixin.insert (package:flutter/src/rendering/object.dart:3288:5)
#5 RenderLayoutBox.insert (package:kraken/src/rendering/box_model.dart:202:11)
#6 KrakenElementToWidgetAdaptor.createRenderObject (package:kraken/src/widget/element_to_widget_adaptor.dart:29:24)
#7 RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5459:28)
#8 KrakenElementToFlutterElementAdaptor.mount (package:kraken/src/widget/element_to_widget_adaptor.dart:65:11)
#9 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3631:14)
#10 Element.updateChild (package:flutter/src/widgets/framework.dart:3380:20)
#11 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4613:16)
#12 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5)
#13 StatelessElement.update (package:flutter/src/widgets/framework.dart:4669:5)
#14 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#15 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6130:14)
#16 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#17 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6130:14)
#18 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#19 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4613:16)
#20 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5)
#21 StatelessElement.update (package:flutter/src/widgets/framework.dart:4669:5)
#22 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#23 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4613:16)
#24 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5)
#25 ProxyElement.update (package:flutter/src/widgets/framework.dart:4943:5)
#26 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#27 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4613:16)
#28 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4763:11)
#29 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5)
#30 StatefulElement.update (package:flutter/src/widgets/framework.dart:4795:5)
#31 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#32 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4613:16)
#33 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5)
#34 StatelessElement.update (package:flutter/src/widgets/framework.dart:4669:5)
#35 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#36 SliverMultiBoxAdaptorElement.updateChild (package:flutter/src/widgets/sliver.dart:1243:37)
#37 SliverMultiBoxAdaptorElement.performRebuild.processElement (package:flutter/src/widgets/sliver.dart:1148:35)
#38 Iterable.forEach (dart:core/iterable.dart:279:35)
#39 SliverMultiBoxAdaptorElement.performRebuild (package:flutter/src/widgets/sliver.dart:1192:24)
#40 SliverMultiBoxAdaptorElement.update (package:flutter/src/widgets/sliver.dart:1126:7)
#41 Element.updateChild (package:flutter/src/widgets/framework.dart:3370:15)
#42 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4613:16)
#43 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4763:11)
#44 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5)
#45 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2578:33)
#46 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
#47 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:363:5)
#48 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1145:15)
#49 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1082:9)
#50 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:996:5)
#54 _invoke (dart:ui/hooks.dart:150:10)
#55 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:270:5)
#56 _drawFrame (dart:ui/hooks.dart:114:31)
(elided 5 frames from class _AssertionError and dart:async)

@answershuto
Copy link
Member

是在最新的 main 上测试的吗?这个问题看起来最近修过,由于重复调用 insert 的缘故。

@zjt123
Copy link
Author

zjt123 commented May 13, 2022

是在最新的 main 上测试的吗?这个问题看起来最近修过,由于重复调用 insert 的缘故。

对的 最新的main测试的, commitid :193b7459d38daa997eea9dfb8bfae320787c5326

@zjt123
Copy link
Author

zjt123 commented May 13, 2022

是在最新的 main 上测试的吗?这个问题看起来最近修过,由于重复调用 insert 的缘故。

有相关的北海交流群吗?方便发一下吗?

@answershuto
Copy link
Member

答疑只走 issue,群内不答疑。交流群可以在 TSC 那边找到。

@answershuto answershuto self-assigned this May 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants