集成PolymerDart和Symfony-第2部分

tech2023-10-09  92

In the previous article, we implemented a Dart widget in our Symfony app. Let's handle the rest now. This might get advanced, so grab a cup of coffee and pay close attention – I recommend you follow along only after completing Part 1!

在上一篇文章中,我们在Symfony应用程序中实现了Dart小部件。 现在让我们处理其余的事情。 这可能会变得更高级,因此请喝杯咖啡并密切注意–我建议您仅在完成第1部分后继续学习!

绕过JSONP并在模板中显示对象的成员 (Get around JSONP and display an Object's member in the template)

If the server (and thus the configuration, the programming) is managed by ourselves, the process to get data from a RESTful API from that same server will be simple. We can enable CORS in the returned response header. Done! But if the remote server's RESTful API does not set that header, we will face a CORS error when we try to invoke that API call from within the Dart app.

如果服务器(以及配置,程序)由我们自己管理,那么从同一服务器的RESTful API获取数据的过程将很简单。 我们可以在返回的响应头中启用CORS。 做完了! 但是,如果远程服务器的RESTful API未设置该标头,则当我们尝试从Dart应用程序中调用该API调用时,我们将面临CORS错误。

One commonly discussed technique is to use JSONP. Dart also has a few packages serving jsonp functionality. You can find these packages here by searching for "jsonp".

一种常用的讨论方法是使用JSONP 。 Dart也有一些提供jsonp功能的软件包。 您可以通过搜索“ jsonp” 在此处找到这些软件包。

However, in our implementation, we will do it another way due to the "hacky" nature of JSONP.

但是,在我们的实现中,由于JSONP的“ hacky”性质 ,我们将采用另一种方式。

It is a fair assumption to say that anyone who is doing web site development should have at least one site under his/her own jurisdiction.

可以肯定地说,任何从事网站开发的人都应在自己的管辖范围内拥有至少一个网站。

In my 2nd Dart widget to be integrated into my homepage, I try to grab some weather information from two different remote servers (and none of them enabled CORS). Obviously I have no control over these two servers, so I do the following:

在要集成到主页中的第二个Dart小部件中,我尝试从两个不同的远程服务器(没有一个启用了CORS)中获取一些天气信息。 显然,我无法控制这两个服务器,因此请执行以下操作:

First, create a controller in Symfony to grab the data from these two remote servers:

首先,在Symfony中创建一个控制器,以从这两个远程服务器中获取数据:

public function WeatherAction($type, $param) { if ($type == 1) // Local weather info { $weather = file_get_contents("http://m.weather.com.cn/data/$param.html"); //101190401 for Suzhou, my hometown } else { $weather = file_get_contents("http://api.openweathermap.org/data/2.5/weather?q=$param&units=metric"); //suzhou,china } $response = $this->render('trrsywxBundle:Default:json.html.twig', array('res' => $weather)); $response = $this->setExtraHeader($response); return $response; }

These two sites all return JSON strings upon calling but neither has set the CORS header. In Dart, such an API call will fail but in Symfony's environment, it is successful – only JavaScript is restricted by CORS, server side languages can still consume resources on other domains. Also note that by wrapping the returns from the remote servers by providing extra headers, we can enable CORS.

这两个站点都在调用时返回JSON字符串,但都没有设置CORS标头。 在Dart中,这样的API调用将失败,但是在Symfony的环境中,它是成功的-只有JavaScript受CORS限制,服务器端语言仍然可以消耗其他域上的资源。 还要注意,通过提供额外的标头包装来自远程服务器的返回值,我们可以启用CORS。

Next, in Dart, we create another Polymer app to get the information grabbed by Symfony and do further processing:

接下来,在Dart中,我们创建另一个Polymer应用程序以获取Symfony捕获的信息并进行进一步处理:

void getWeather() { var path1='http://rsywx/app_dev.php/json/weather/1/$code'; var path2='http://rsywx/app_dev.php/json/weather/2/$city'; HttpRequest.getString(path1).then((String res)=>processWeather1(res)); HttpRequest.getString(path2).then((String res)=>processWeather2(res)); if(one) one=false; else one=true; } void processWeather1(String res) { w1=new Weather1.created(res); } void processWeather2(String res) { w2=new Weather2.created(res); } }

After retrieving the data from our own Symfony site, the process is straightforward.

从我们自己的Symfony网站检索数据后,该过程非常简单。

In this implementation, every "Refresh" will grab weather info from both servers. It can be fine tuned to eliminate redundant API calls by determining what we are to show for the "Refresh" click (variable one toggles its Boolean status every time we calls the getWeather function, which is invoked by every "Refresh" request).

在此实现中,每个“刷新”将从两台服务器中获取天气信息。 它可以进行微调,以消除通过确定我们所展现的“刷新”键(可变冗余API调用one我们每次调用时切换的布尔状态getWeather功能,这是每一个“刷新”请求调用)。

one is also used in our Dart Polymer template to decide which weather information is to be displayed as these two pieces of information will share a same slot in our HTML flow. The HTML template to show weather information is something like this:

在我们的Dart Polymer模板中还使用了one来确定要显示的天气信息,因为这两条信息将在我们HTML流中共享相同的位置。 显示天气信息HTML模板如下所示:

<polymer-element name="weather-tag" attributes="city code"> <template> <meta charset="utf-8"> <template if='{{!one}}'> <div class="ui message"> //Display local weather information </div> </template> <template if='{{one}}'> <div class="ui message"> //Display local weather information from another source </div> </template> </template> <script type="application/dart" src="weather.dart"></script> </polymer-element>

We declared two classes to simplify the instantiation of our weather information and for easier access. The Weather2 class is shown below:

我们声明了两个类,以简化我们的天气信息的实例化并简化访问。 Weather2类如下所示:

class Weather2 { @observable var desc, city, temp, humidity; Weather2.created(String s) { Map w=JSON.decode(s); this.temp=w['main']['temp'].toStringAsFixed(1); this.humidity=w['main']['humidity']; this.city=w['name']; this.desc=w['weather'][0]['description']; } }

Basically, we just extract certain data from the returned JSON string and put them into the members of the class.

基本上,我们只是从返回的JSON字符串中提取某些数据,然后将它们放入类的成员中。

Special attention should be paid to the declarations of the class members. We have decorated them with @observable. This is to prevent Dart compile-time tree shaking from dropping the reference of these class members as (and most likely the reason is) they are not explicitly referenced anywhere in a Polymer expression in our Dart program when it is compiled to JavaScript. Thanks for Günter Zöchbauer for the tip in my question raised in StackOverflow.

应特别注意班级成员的声明。 我们已经用@observable装饰了它们。 这是为了防止Dart编译时树动摇晃丢弃这些类成员的引用,因为(很可能是因为)当Dart程序编译为JavaScript时,它们没有在我们的Dart程序的Polymer表达式中的任何地方显式引用。 感谢GünterZöchbauer 在StackOverflow中提出的问题提示。

This is not required to run the app in Dartium. But it is a MUST if we compile it to JS.

不需要在Dartium中运行该应用程序。 但是,如果我们将其编译为JS,则必须这样做。

With the help of the defined Weather class, we can display the object in Polymer template in a more OO way:

借助已定义的Weather类,我们可以以一种更加OO的方式在Polymer模板中显示对象:

<template if='{{one}}'> <div class="ui message"> <p>Today in {{w2.city}}: {{w2.desc}}, temperature {{w2.temp}} celcius, humidity {{w2.humidity}}% <br><i title="Refresh" class="refresh icon small link" on-click="{{getWeather}}"></i></p> </div> </template>

Without using the class, we can name our variables as w2city, w2temp, etc. But that is neither very user-friendly, nor developer-friendly, right?

在不使用类的情况下,我们可以将变量命名为w2city , w2temp等。但这既不是非常用户友好的,也不是开发人员友好的,对吗?

两个Dart,一个HTML? Dart的局限性 (Two Dart, One HTML? Limitation of Dart)

So far the process is smooth. Now I need to integrate the above two created Dart widget into the same homepage. Without hesitation, I modified my HTML template to something like this:

到目前为止,该过程很顺利。 现在,我需要将以上两个创建的Dart小部件集成到同一主页中。 我毫不犹豫地将HTML模板修改为如下形式:

<!DOCTYPE html> <html lang="zh-CN"> <head> <script src="/packages/shadow_dom/shadow_dom.debug.js"></script> <script src="/packages/custom_element/custom-elements.debug.js"></script> <script src="/packages/browser/interop.js"></script> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="/css/semantic.css"> <link rel="stylesheet" type="text/css" href="/css/rsywx.css"> <script src="/getqotd.html_bootstrap.dart.js"></script> <script src="/getweather.html_bootstrap.dart.js"></script> <title>...</title> </head> <body id="home"> <polymer-element name="qotd-tag"> <template> ... </template> </polymer-element> <polymer-element name="weather-tag" attributes="city code"> <template> ... </template> </polymer-element> {% block content %} <div class="ui inverted page grid masthead segment"> <div class="ui grid"> <div class="row"> <div class="ten wide column"> <qotd-tag></qotd-tag> <weather-tag code="101190401" city="Suzhou,china"></weather-tag> </div> </div> </div> </div>

We inserted the necessary files, in particular, the two compiled JS files and declared the tags, then insert the tags where they are needed, following exactly the steps described earlier.

我们插入了必要的文件,特别是两个已编译的JS文件,并声明了标签,然后按照前面所述的步骤将标签插入需要的地方。

Looks promising, right?

看起来很有前途吧?

Unfortunately, NO.

抱歉不行。

In the above implementation, only the widget whose JS is imported first (qotd) can be displayed properly. If we switch the sequence of the two JS import to make weather JS gets imported first, only the weather widget can be displayed.

在上述实现中,仅可以正确显示其JS首先导入的窗口小部件( qotd )。 如果我们切换两个JS导入的顺序以使weather JS首先被导入,则只能显示weather小部件。

I believe the issue is due to the compiled two JS files having many conflicts in function names, prototype declarations etc. For example, we can find the below declarations in both files:

我认为问题是由于两个已编译的JS文件在函数名称,原型声明等方面存在许多冲突。例如,我们可以在两个文件中找到以下声明:

ght:function(a){return new P.C7(this,P.WV.prototype.h,a,"h")}, zw:function(a,b){if(this.Gv>=4)throw H.b(this.q7()) this.pb(a,b)},

Thus, only one JS can survive and function. Only, it's strange to me why the 2nd JS fails (instead of overriding everything in the 1st JS).

因此,只有一个JS可以生存和运行。 只是,对我来说奇怪的是第二个JS为什么失败(而不是覆盖第一个JS中的所有内容)。

To get around this, we have to create one more Dart/Polymer app, importing both Dart files created in previous steps for QOTD and weather. Then we need to wrap these two Dart widgets into a new widget.

为了解决这个问题,我们必须再创建一个Dart / Polymer应用程序,同时导入在先前步骤中为QOTD和天气创建的Dart文件。 然后,我们需要将这两个Dart小部件包装到一个新的小部件中。

The Github repository contains the final Dart application which is working fine. I have put a Youtube video to demonstrate the result (sorry to say that the homepage is mostly in Chinese but you will see how Dart goes into a Symfony page and responds to user interaction. You may need to switch to 720p to get a clearer view.)

Github存储库包含运行良好的最终Dart应用程序。 我放了一个Youtube视频来演示结果(很抱歉,该主页主要是中文的,但是您会看到Dart如何进入Symfony页面并响应用户交互。您可能需要切换到720p以获得更清晰的视图)

This is obviously a big drawback in Dart-compiled JS.

在Dart编译的JS中,这显然是一个很大的缺点。

This is not flexible and makes expanding difficult. We are now integrating two widgets. What if we want to see some stock quotes later on? My favorite team's score? A news feed? Is the only option developing a new or modifying an existing Dart widget every time we need to add or delete a widget component?

这不灵活并且使扩展变得困难。 我们现在正在集成两个小部件。 如果我们以后想要看到一些股票报价怎么办? 我最喜欢的球队得分? 新闻提要? 每当我们需要添加或删除小部件组件时,唯一的选择是开发新的还是修改现有的Dart小部件?

This approach will work, of course, but with very low efficiency. Besides, not all web developers are Dart developers at the same time. To ask a web developer to open up a Dart IDE and start Dart coding to insert a simple new component is not practical.

这种方法当然可以,但是效率非常低。 此外,并非所有的Web开发人员都是Dart开发人员。 让Web开发人员打开Dart IDE并开始Dart编码以插入一个简单的新组件是不切实际的。

Why can't we have a Dart development such that Dart (and Dart programmers) can build various self-contained widgets (components) and the web developer can just grab the compiled JS/html/CSS/image files and just modify the web pages and start formulating a "new" widget? If this could be done, Dart would reach widespread acceptance much faster.

为什么我们不能进行Dart开发,以使Dart(和Dart程序员)可以构建各种独立的小部件(组件),而Web开发人员可以仅获取已编译的JS / html / CSS /图像文件,而仅修改网页并开始制定“新”小部件? 如果能够做到这一点,Dart将更快地被广泛接受。

This is a confirmed issue in Dart. A feature request has been posted to the Dart Google Group to seek their attention and further improvement. Help out by voting on it.

这是Dart中已确认的问题。 一项功能请求已发布到Dart Google小组,以寻求他们的关注和进一步的改进。 通过投票帮助它。

结论 (Conclusion)

In this series, we demonstrated how to integrate Dart/Polymer into Symfony to bring our page dynamic contents and user interaction. A detailed step-by-step instruction was given to help users to manage the integration, in particular, to insert the Polymer template into the Twig engine.

在本系列中,我们演示了如何将Dart / Polymer集成到Symfony中以带来页面动态内容和用户交互。 提供了详细的分步说明,以帮助用户管理集成,尤其是将Polymer模板插入Twig引擎。

Also, we covered several topics in Dart programming: get around the JSONP and display objects in the Polymer template.

此外,我们还介绍了Dart编程中的几个主题:绕过JSONP并在Polymer模板中显示对象。

Finally, we highlighted the limitation in current Dart JS compilation: two or more separate Dart apps can't live in one HTML unless a new wrapping Dart app is created. I do hope this issue is resolved as soon as possible.

最后,我们强调了当前Dart JS编译的局限性:除非创建了一个新的包装Dart应用程序,否则两个或多个单独的Dart应用程序不能存在于一个HTML中。 我希望这个问题能尽快解决。

This brings us the end of this series. Feel free to comment and raise questions!

这使我们结束本系列文章。 随时发表评论并提出问题!

翻译自: https://www.sitepoint.com/integrating-polymerdart-symfony-part-2/

相关资源:jdk-8u281-windows-x64.exe
最新回复(0)