[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> -->

如何在 Rails 中搭配 Turbolinks 使用 Vue的更多相关文章

  1. 如何在Rails中执行Get/Post/Put请求

    require 'open-uri' require 'json' require 'net/http' class CoupleController < ApplicationControll ...

  2. 如何在 Vite 中使用 Element UI + Vue 3

    在上篇文章<2021新年 Vue3.0 + Element UI 尝鲜小记>里,我们尝试使用了 Vue CLI 创建 Vue 3 + Element UI 的项目,而 Vue CLI 实际 ...

  3. Vue:如何在vue-cli中创建并引入自定义组件

    一.创建并引入一个组件 1.创建组件 vue-cli中的所有组件都是存放在components文件夹下面的,所以在components文件夹下面创建一个名为First.vue的自定义组件: <t ...

  4. rails中如何在a标签中添加其他标签

    最近在用rails写一个项目练练手,然后遇到了一个问题,就是用 <% link_to("首页", root_path) %> 生成一个a标签,之后就在想我怎么在这个a标 ...

  5. 我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  6. 【转】我是如何在SQLServer中处理每天四亿三千万记录的

    原文转自:http://blog.jobbole.com/80395/ 首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文 ...

  7. 如何在Vue2中实现组件props双向绑定

    Vue学习笔记-3 前言 Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能. 以往在Vue1.x中利用pr ...

  8. 如何在SQLServer中处理每天四亿三千万记录

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  9. (转)我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

随机推荐

  1. 从wireshark数据中分析rtmp协议,并提取出H264视频流

    我写的小工具 rtmp_parse.exe 使用用法如先介绍下: -sps  [文件路径] 解析 sps 数据 文件当中的内容就是纯方本的hexstring: 如 42 E0 33 8D 68 05 ...

  2. 使用java来压缩图片

    使用java来压缩图片,简单几句,清清爽爽 使用0.3的压缩比得到的结果如下(从2.8M压缩到268K,且图片的清晰度看不出明显差别): package carlspringtest; import ...

  3. JAVA加密解密DES对称加密算法

    下面用DES对称加密算法(设定一个密钥,然后对所有的数据进行加密)来简单举个例子. 首先,生成一个密钥KEY. 我把它保存到key.txt中.这个文件就象是一把钥匙.谁拥有它,谁就能解开我们的类文件. ...

  4. NGUI类之间的关系架构

    NGUI Drawcall 1.使用同一个altals的元素尽量放在同一个UIPanel下面,在NGUI中,它消耗的drawcall是以每个Panel为独立计算单位进行计算的. 2.如果一个UIPan ...

  5. springboot 测试

    本次测试使用的是springboot 中的测试 1.(对service 的测试)下面的测试.将会启动容器进行测试 @RunWith(SpringRunner.class) @SpringBootTes ...

  6. FiraCode 字体 => 箭头函数变成 整体 还有 等于 不等于

    https://github.com/tonsky/FiraCode Enable in Settings → Editor → Color Scheme → Color Scheme Font →  ...

  7. 2018.3.26 Linux下学习命令

    Linux下的终端文件颜色说明 ---color[=WHEN] 用色彩辨别文件类型 WHEN 可以是'never'.'always'或'auto'其中之一 白色:表示普通文件 蓝色:表示目录 绿色:表 ...

  8. 绘制方式和OpenGL枚举对应关系

    绘制方式和OpenGL枚举对应关系 图元类型 OpenGL枚举量 点 GL_POINTS 线 GL_LINES 条带线 GL_LINE_STRIP 循环线 GL_LINE_LOOP 独立三角形 GL_ ...

  9. webpack4 + vue多页面项目精细构建思路

    #构建思路 虽然当前前端项目多以单页面为主,但多页面也并非一无是处,在一些情况下也是有用武之地的,比如: 项目庞大,各个业务模块需要解耦 SEO更容易优化 没有复杂的状态管理问题 可以实现页面单独上线 ...

  10. HTML5<section>元素

    HTML5<section>元素用来定义页面文档中的逻辑区域或内容的整合(section,区域),比如章节.页眉.页脚或文档中的其他部分. 根据W3C HTML5文档中:section里面 ...