问题
I see 3 ways of doing this.
- Using
<%= %>
inside<script>
in*.html.eex
- Use channels to pass data to Javascript
- Build a json api
#1 seems the easiest but I couldn't find or think of a good way to do it yet.
Note: real-time update is not my requirement.
回答1:
I would never use a <script></script>
for that, in my projects I have this pattern:
<!-- Layout -->
<div id="config"
data-environment="..."
></div>
I always provide the current environment in the master layout, I have a config.js
file with the right data for the right environment.
When I need to pass some data to my javascript I do something like that in my view:
<div id="app"
data-users="..."
data-zombies="..."
...
></div>
If you abstract that with some helpers (elixir side) you can do:
<%= App.Helpers.make_html(:app, [users: @users, zombies: @zombies]) %>
In the javascript side, when I load the page I just extract the data-
attributes and set them in a variable options
for the current controller:
class ZombieController extends Controller
setup: ->
console.log(@options) # I have all the data there.
# I can do
zombies = @options.zombies
Well, it's just an example and you should adapt that for your current project. The key is to abstract.
Hope it helps :)
回答2:
(2) is not a good idea if you don't want real time updates. (3) may be too unnecessarily complicated if you don't want to load the data using AJAX. You should use (1) if you just need some data to be accessible from JS and don't want to change it without a whole page reload.
Since valid JSON is also valid JS, you can just use Poison.encode!()
. If your data is in @posts
, you can do this in *.html.eex
:
<script>
var POSTS = <%= Poison.encode!(@posts) %>;
</script>
and then load other JS after this and access the posts using the global POSTS
variable. (You might want to namespace it into something like App.posts = ...
:
<script>
var App = window.App || {};
App.posts = <%= Poison.encode!(@posts) %>;
</script>
Make sure @posts
only contains data that can be converted to JSON (no tuples) and only has the fields that the user is allowed to see.
回答3:
Best Practice depends on your front end.
If you are basically serving HTML with dribbles of javascript. Inject data into the html or via script tag
If you are building a react / angular / front end, then consider using an API and/or Channels.
In general, if it's a significant web app that will require data to be manipulated via javascript, I'd go the API/Channel route.
回答4:
Also you can use hex PhoenixGon it uses the first way for passing Phoenix variables to Javascript. It takes all variables from controller and Mix.env and generate <script>
tag with rendered JSON
and methods for accessing to this data. See other answeres here. It's like:
def index(conn, _params) do
conn = put_gon(conn, [users: Repo.all(Users), zompies: Repo.all(Zombies)])
render(conn, "index.html", current_user: get_session(conn, :current_user))
end
And in js Code:
window.Gon.getAsset('users') #=> [user list]
windoe.Gon.isDev() # => true
And you don't need create @vars and keep it clear.
And for zommbies.coffee
:
class ZombieController extends Controller
setup: ->
zombies = window.Gon.getAsset('zombies')
来源:https://stackoverflow.com/questions/39052160/best-practice-to-pass-data-from-phoenix-to-javascript