I've tried 2 ways that both work but neither feel very clean.
The first is to have some inline javascript that accepts the variable from the view template like:
var x = {{ myServersideVariable }};
(In my case I'm using Jinja2 but same thing would apply to Django templates, Razor in .NET MVC3, Twig in PHP or any number of view templating engines).
Obviously the unclean part about this that there's javascript in the html page rather than in a separate file.
The other option I've used is to have a hidden field populated server side and then consumed on the Javascript end. That feels slightly more clean, but not completely and it's also a bit cumbersome to write.
Is there a better solution or are those pretty much my only options?
P.S.
I'm aware of JSON and in fact I do sometimes have to resort to the first solution if I need to pass something other than primitives. So bonus points for a solution that supports passing JSON objects without having javascript on the page.There are only two correct ways to inject data from the server into javascript.
You either expose the data as a service. You can have a REST service or whatever you like and then query it with ajax to extract data from it.
The other option is to inject the data into the HTML. You want to use JavaScript to progressively enhance your page. So that data already needs to exist in the HTML, and your JavaScript will extract it from the HTML.
Now if your going for a JavaScript heavy application which can't be supported without JavaScript then you want your data to be a REST service.
You do not want to inject it into a serialized hidden field because then your html markup does not have the semantics of the data. You do not want inject it directly into a var x = ...
statement because then your compiling your JavaScript on the fly. This breaks the seperation of concerns.
If the data you want to make accessible to the client-side JavaScript is known at the time the HTML page is requested/generated and will not change until the next time the page is requested then I would not use AJAX because obviously that results in an extra request: one to get the main page, and then another immediately on load to make the AJAX call for the data. That's going to reduce performance and pointlessly complicate both the client and server code.
There's nothing wrong with creating one or more hidden inputs with the data and accessing from your JavaScript code. Depending on the values you want to pass it may be easier to inject the values directly into JS variables in a <script>
section on your page, similar to the example you give, and personally I find that easier to read than hidden inputs because the <script>
section will be prominant at the top of the page rather than having inputs buried somewhere amongst the HTML, and it makes it obvious that the values are intended to be consumed by your code on the client-side and not just submitted back with other form data. But either way is not "unclean".
If you need to get the server-side data into your JavaScript as a response to something the user did on the page after it loaded (clicking a button or something), or if you want to poll the server at regular intervals to check if the values have changed, then you want to use AJAX.
EDIT: note that although you can dynamically generate JS script files on the server and thus keep your dynamic values out of the HTML page entirely sometimes this doesn't work very well because certain browsers can get confused and keep using an earlier cached version of the JS. I've had this happen with older versions of IE.
Use JSON to pass variables from the server to the client as it's a very popular and well supported format. PHP, Python, Java and - what's most important - JavaScript handle it really well. You don't have to care about character escaping etc.
// PHP Example
$vars = array(
'a' => 'def',
'c' => 'xyz',
'e' => array(1, 34, 766, 844)
);
...
var variablesFromServer = <?php echo json_encode($vars) ?>;
// or using Twig
var variablesFromServer = {{ vars|json_encode }};
alert(variablesFromServer.e[2]); // output: 766
It looks very similar in other languages.
You could always use a single entry point (variablesFromServer
variable) to pass all the information that should be passed from the server to the client. That would make your code clean and easy to maintain.
Final usage - from the client perspective - is also really easy:
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
<script>
var variablesFromServer = ...;
MyProject.setConfiguration(variablesFromServer.config);
MyProject.setRuntimeVariables(variablesFromServer.runtime);
MyProject.run();
</script>
One solution that I just thought of of is server-generated javascript files. I like it from a clean-code and separation of concerns perspective but it may kill any kind of browser-caching, so it would depend on how important performance is.
精彩评论