Monday, January 9, 2017

Re: Vue GWT: Vue.JS integration for GWT 2.8


=> Java to JS component translation

Indeed the Java introspection at runtime is also not my favorite thing. Adding a $ before each property name could be a valid solution and I'm surely considering it :).
This will also negate the need to filter out properties manually (like the ___ that is too generic), because only the "interesting" properties would be copied over.

I'm no longer sure that would work. Even if I prefix my "to-go-in-data {}" fields in the Java class with $ so as to signal VueGwt to only put these properties in data {}, Vue monitors the properties defined in data {} recursively. So if I have a field which is OK to go in data {} but the object kept inside this field itself has fields which should not be monitored by Vue, there is no way to tell Vue not to do so... Just look at Vue's state.js & observer.js code...
 

For the @JsProperty, sadly they still would need it (or at least a @JsType + public properties), as the Vue.JS template are not parsed by GWT. The name in the template must match the ones in the JS translation of the Java component. If GWT rename them at compile time, then you'll get for example:
{{ bob }} in your template and data: {a: "hello"} in your component.

That's correct.

 

=> Circular reference in data model.

I tried to create in pure Vue.JS a component that returns a circular reference upon creation, and it also breaks:
(if you remove the test.circular = test, it works again).

Also Vue doc in v1 specifically said that it needs not not contain circular reference. In the v2 they say that you can clone the data using JSON.stringify(JSON.parse(...));

Fixing the way we build the Component data to make sure to only integrate the properties needed by the user would probably make this less of an issue.

I think the "return JSON.parse(JSON.stringify(data));" trick that you do in VueGwtTools.js has to go. 
For one, this call completely disconnects the original set of fields in data {}, from the ones that Vue will monitor. So I'm not sure that the current VueGwt implementation monitors the correct fields at all?

Also, a copy of the data {} is anyway required in Vue.js only when you register a new Vue component (as opposed to just instantiating a new Vue instance): https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
Perhaps the misunderstanding and the mismatch comes from how you register a new component. In  your example, you do it like this:
@JsType  public class RootComponent extends VueComponent  {      public RootComponent()      {          // ChildComponent is registered to be used in our RootComponent          this.registerComponent(new ChildComponent());      }  }

In Java and also with your approach where data {}, props {} methods {} and all are flattened in a single Java object, it would feel much more natural if you do it like this:
@JsType  public class RootComponent extends VueComponent  {      public RootComponent()      {          // ChildComponent is registered to be used in our RootComponent          this.registerComponent(ChildComponent.class);      }  }

... and then VueGwt should map a JS function to the Vue "data" property which function should instantiate a fresh instance of the ChildComponent class, ending up with a separate data {} copy for each new component instance, as is required.
(It is another topic how to do this reflective instantiation of the component with GWT anyway. Perhaps you need a Factory pattern here, in the absence of reflection in GWT?)

 

=> Minor issues

1: Yes, for now we just wanted to get feedback, so it wasn't needed, but if people show interest it will happen.

2: Indeed, nice catch! I'll make sure to add it to the documentation.


=> Other questions

As you saw even if the Java introspection is nice and pretty easy to do (with naming convention), it doesn't not feel very "Java" or clean to code with it. I was thinking about using annotations with annotations processor to avoid having naming conventions.

For example a simple component could look like:
@Component
public class myComponent extends VueComponent {
  @VueData
  protected String myMessage = "Hello";

  @VueMethod
  protected void resetMessage() {
    this.myMessage = "";
  }

  @VueWatch
  protected void myMessage() {
    // Do something
  }
}

This would be much cleaner to code. Also it might be possible to automatically bind templates, we would also gain the ability to fine tune the component behavior by passing parameters to the @Component annotation.

My main issue with this is after doing some research, it seems that annotation processors integrates poorly for now with GWT super dev mode. You have to manually rereun the annotation processor after each change. I do think the code would look nice with annotations, but if developing with it becomes slow and cumbersome, then there is not really a point.

 
I wonder what you think of this idea, and if you have any experience with annotation processor in GWT ?

That would be nice. I have no experience with annotation processors myself, unfortunately. I think Angular2-Gwt uses this approach, isn't it? Perhaps you can contact the Angular2-Gwt maintainer for further info on the subject.

But then: even with that approach you have the "recursion" problem I mentioned at the top of my reply (Vue.js traversing all properties in data {} recursively), isn't it?



--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment