[Rails] Vue-outlet for Turbolinks

在踩了 Rails + Turbolinks + Vue 的許多坑後,整理  的作法並和大家分享。

Initialize the App

# initialize the app
rails new rails_sandbox_vue --database=postgresql --webpack=vue # install package
bundle
yarn

Scaffold the app

# Scaffold the app
bin/rails g scaffold User name email # Create database and migrate
bin/rails db:setup
bin/rails db:migrate

Create Vue Component

在 ./app/javascript/packs/ 中建立 vue component hello_turbolinks.vue

<!--
./app/javascript/packs/hello_turbolinks.vue
--> <template>
<div>
<h4>{{ message }}</h4>
<ul>
<li>Object: {{ obj }} </li>
<li>Number: {{ num }} </li>
<li>Array: {{ arr }} </li>
<li>String: {{ str }} </li>
</ul>
</div>
</template> <script>
export default {
props: ['obj', 'arr', 'num', 'str'],
data: function () {
return {
message: 'Hello, Vue and Turbolinks'
}
}
}
</script> <style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>

Create Vue Adapter

建立 vue_adapter.js,在 import Vue 的地方要載入 vue.esm.js 可以 compile template 的版本。另外要把需要使用到的 Vue Component 在這裡執行註冊:

// ./app/javascript/packs/vue_adapter.js
import Vue from 'vue/dist/vue.esm.js'
import HelloTurbolinks from './hello_turbolinks' /**
* Register components
*/
Vue.component('hello-turbolinks', HelloTurbolinks) function VueConstructor () {
let outlets = document.querySelectorAll('www.rcsx.org [data-vue-components-outlet]')
outlets.forEach(function (outlet, index) {
let id = outlet.getAttribute('data-vue-components-outlet')
new Vue({
el: '[data-vue-components-outlet=' + id + ']'
})
})
} document.addEventListener('turbolinks:load', function () {
VueConstructor()
})

Notice:
-記得 import 的 Vue 要匯入的是 vue.esm.js
-記得註冊要使用的 Vue Component

add vue_adapter in head

在 layouts/application.html.erb 中的 head 中加入 <%= javascript_pack_tag 'vue_adapter', 'data-turbolinks-track': 'reload' %>

<!--
./app/views/layouts/application.html.erb
-->
<!DOCTYPE html>
<html>
<head>
<title>RailsSandboxVue</title>
<%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'vue_adapter', 'data-turbolinks-track': 'reload' %>
</head> <body>
<%= yield %>
</body>
</html>

Notice: 記得要把 javascript_pack_tag 放在 head 當中

Import Vue component in template

我們把 Vue 的組件載入 index.html.erb 中,data-vue-components-outlet 這個屬性是關鍵字,後面放要載入的 Vue 組件名稱:

<!--
./app/views/users/index.html.erb
--> <!-- 以上省略 -->
<% @hello_message = {num: 1, str: '2', arr: [1, 2, 3], obj: {name: 'foo', age: 12}} %> <!-- Import Vue Component -->
<div data-vue-components-outlet="hello-turbolinks">
<hello-turbolinks
:obj="<%= @hello_message[:obj].to_json %>"
:arr="<%= @hello_message[:arr] %>"
:str="<%= @hello_message[:str] %>"
:num="<%= @hello_message[:num] %>"
></hello-turbolinks>
</div>
<!-- End of Import Vue Component --> <%= link_to 'New User', new_user_path %>

完成

分別開兩個 terminal 到 app 目錄底下,分別執行:

bin/webpack-dev-server
bin/rails s

就可以看到 Vue Component 正確運作了。

加入 View Helper

我們也可以寫一個 Rails View Helper 來方便我們使用 Vue 組件:

在 ./app/helpers/ 中建立一支 vue_helper.rb

# ./app/helpers/vue_helper.rb
module VueHelper
def vue_outlet(html_options = {})
html_options = html_options.reverse_merge(data: {})
html_options[:data].tap do |data|
data[:vue_components_outlet] = "_v" + SecureRandom.hex(5)
end
html_tag = html_options[:tag] || :div
html_options.except!(:tag)
content_tag(html_tag, '', html_options) do
yield
end
end
end

使用方式如下:

<!--
./app/views/users/index.html.erb
--> <% @hello_message = {num: 1, str: '2', arr: [1, 2, 3], obj: {name: 'foo', age: 12}} %> <!-- Import Vue Component by Helper -->
<%= vue_outlet do %>
<hello-turbolinks
:obj="<%= @hello_message[:obj].to_json %>"
:arr="<%= @hello_message[:arr] %>"
:str="<%= @hello_message[:str] %>"
:num="<%= @hello_message[:num] %>"
>
<% end %>
<!-- End of Import Vue Component by Helper -->

如果需要 tag 不想要使用 div 可以加上 options:

 
<!--
./app/views/users/index.html.erb
--> <!-- With <p> -->
<%= vue_outlet tag: 'p' do %>
<hello-turbolinks
:obj="<%= @hello_message[:obj].to_json %>"
:arr="<%= @hello_message[:arr] %>"
:str="<%= @hello_message[:str] %>"
:num="<%= @hello_message[:num] %>"
>
<% end %>
<!-- End of With <p> -->

最新文章

  1. JavaWeb学习笔记——表达式语言
  2. servlet实现的三种方式对比(servlet 和GenericServlet和HttpServlet)
  3. anroid
  4. git学习笔记04-将本地仓库添加到GitHub远程仓库-git比svn先进的地方
  5. TFS使用指南
  6. Agile software architecture design document style..( sketches and no UMLs)
  7. count(1) count(*)
  8. cookie : 存储数据
  9. css sprint 生成工具 bg2css
  10. IT忍者神龟之Struts2.xml配置全然正确流程能走通可是有红叉解决
  11. vs2008编译QT开源项目三国杀(五篇文章)
  12. vue中实现图片全屏缩放预览,支持移动端
  13. java 开发环境配置 安装 MyEclipse
  14. nexus的安装和简介(2)
  15. 分布式监控系统Zabbix-3.0.3-完整安装记录(3)-监控nginx,php,memcache,Low-level discovery磁盘IO
  16. Python中可视化图表处理echarts库的安装
  17. 通过jdbc获取数据库中的表结构 主键 各个表字段类型及应用生成实体类
  18. zookeeper知识点学习
  19. Java项目中读取properties文件,以及六种获取路径的方法
  20. url get与post 请求长度限制

热门文章

  1. git如何强制用远程分支更新本地
  2. IM云通信行业步入快车道,谁将成为代表中国的全球IM“独角兽”?
  3. 为Oracle Clusterware修改公用及私有网络接口
  4. HDU 5091 Beam Cannon (扫描线思想)
  5. coredata 删除与更新
  6. Java 集合框架_下
  7. Windows环境下使用Apache+mod
  8. java基础—注解annotation
  9. Unity3d 中键值监听方法
  10. MATLAB编程技巧