一种在服务器端预编译 slim 模板并在 Rails 应用程序中将 HTML 传递给 VueJS 的方法?
A way to precompile slim templates on server side and pass HTML to VueJS in Rails app?
我正在尝试将 Vue js 集成到现有的 rails 应用程序中,其中包含许多超薄模板。如果我可以在 slim 模板中使用 vue 指令就好了
(是的,这是可能的),获取一个 HTML 并将其传递给 Vue 实例以供进一步开发。我知道有 slim-lang 加载器可以将 slim 编译为 html,或者您可以在 <template lang="slim">
中使用 slim 语法。
但我不想通过 AJAX 单独发送每个 ruby/rails 方法的结果。我希望 Rails 完成它的工作并将结果 HTML 提供给 Vue 实例。对此有何想法和建议?
没有结合服务器端和客户端模板的灵丹妙药。即使您可以在服务器上呈现 vue 模板,关键上下文也会丢失(客户端页面的交互状态)。
有一些相当简单但有缺陷的技术可用于组合服务器端和客户端呈现:
创建一个为您的视图提供服务的控制器
Rails.application.routes.draw do
scope 'templates' do
get '*path', to: 'templates#show'
end
end
class TemplatesController < ApplicationController
def show
if lookup_context.exists?(params[:path])
render template: params[:path]
else
head :not_found
end
end
end
require 'rails_helper'
RSpec.describe "Templates", type: :request do
describe "GET /template/*path" do
it "fetches template if it exists" do
get '/templates/foo/bar.html.erb'
expect(response).to have_http_status(200)
expect(response.body).to match "TEST"
end
it "returns 404 if it does not exist" do
get '/templates/foo/non_existant.html.erb'
expect(response).to have_http_status(:not_found)
end
end
end
然而,细节决定成败 - 只有当您的视图完全静态并且不需要任何输入数据时,这才会真正起作用。
在没有布局的情况下呈现视图
如果您希望从控制器正常呈现但不包括整个布局,您可以注册自定义格式:
# config/initializers/mime_types.rb
Mime::Type.register "text/x-html-template", :template
有时您可能需要停止 spring 以便获取配置更改。
然后您可以禁用此格式的布局:
class ApplicationController < ActionController::Base
before_action :add_html_to_template_lookup!, if: -> { request.format.template? }
layout :is_template_request?
private
def is_template_request?
request.format.template? ? false : "application"
end
# this will make rails fall back to rendering the "normal" html views
def add_html_to_template_lookup!
request.formats << Mime::Type.lookup("text/html")
end
end
我找到的解决方案非常简单。您需要做的就是将您的 slim 标记包装在您的 .slim 视图中的 vue 组件标签内,并向其添加 inline-template 属性。
示例:
# header.html.slim
<v-header inline-template>
header
nav
- categories.each do |category|
= link_to category.name, category, '@click.prevent': 'doSomething'
</v-header>
或
v-header inline-template=""
header
nav
- categories.each do |category|
= link_to category.name, category, '@click': 'doSomething'
Ruby 代码将首先执行,模板引擎将使用 vue 指令将所有内容转换为 html,然后 Vue 将识别其指令并控制标记。在我实现这个之后,我摆脱了 jquery 和资产管道。但观点是一样的。我没有将任何 html 个文件迁移到 vue 组件。使用此功能,您可以将 Vue js 部分应用到现有的 rails 项目并开始编写现代 javascript 代码。
我正在尝试将 Vue js 集成到现有的 rails 应用程序中,其中包含许多超薄模板。如果我可以在 slim 模板中使用 vue 指令就好了
(是的,这是可能的),获取一个 HTML 并将其传递给 Vue 实例以供进一步开发。我知道有 slim-lang 加载器可以将 slim 编译为 html,或者您可以在 <template lang="slim">
中使用 slim 语法。
但我不想通过 AJAX 单独发送每个 ruby/rails 方法的结果。我希望 Rails 完成它的工作并将结果 HTML 提供给 Vue 实例。对此有何想法和建议?
没有结合服务器端和客户端模板的灵丹妙药。即使您可以在服务器上呈现 vue 模板,关键上下文也会丢失(客户端页面的交互状态)。
有一些相当简单但有缺陷的技术可用于组合服务器端和客户端呈现:
创建一个为您的视图提供服务的控制器
Rails.application.routes.draw do
scope 'templates' do
get '*path', to: 'templates#show'
end
end
class TemplatesController < ApplicationController
def show
if lookup_context.exists?(params[:path])
render template: params[:path]
else
head :not_found
end
end
end
require 'rails_helper'
RSpec.describe "Templates", type: :request do
describe "GET /template/*path" do
it "fetches template if it exists" do
get '/templates/foo/bar.html.erb'
expect(response).to have_http_status(200)
expect(response.body).to match "TEST"
end
it "returns 404 if it does not exist" do
get '/templates/foo/non_existant.html.erb'
expect(response).to have_http_status(:not_found)
end
end
end
然而,细节决定成败 - 只有当您的视图完全静态并且不需要任何输入数据时,这才会真正起作用。
在没有布局的情况下呈现视图
如果您希望从控制器正常呈现但不包括整个布局,您可以注册自定义格式:
# config/initializers/mime_types.rb
Mime::Type.register "text/x-html-template", :template
有时您可能需要停止 spring 以便获取配置更改。
然后您可以禁用此格式的布局:
class ApplicationController < ActionController::Base
before_action :add_html_to_template_lookup!, if: -> { request.format.template? }
layout :is_template_request?
private
def is_template_request?
request.format.template? ? false : "application"
end
# this will make rails fall back to rendering the "normal" html views
def add_html_to_template_lookup!
request.formats << Mime::Type.lookup("text/html")
end
end
我找到的解决方案非常简单。您需要做的就是将您的 slim 标记包装在您的 .slim 视图中的 vue 组件标签内,并向其添加 inline-template 属性。
示例:
# header.html.slim
<v-header inline-template>
header
nav
- categories.each do |category|
= link_to category.name, category, '@click.prevent': 'doSomething'
</v-header>
或
v-header inline-template=""
header
nav
- categories.each do |category|
= link_to category.name, category, '@click': 'doSomething'
Ruby 代码将首先执行,模板引擎将使用 vue 指令将所有内容转换为 html,然后 Vue 将识别其指令并控制标记。在我实现这个之后,我摆脱了 jquery 和资产管道。但观点是一样的。我没有将任何 html 个文件迁移到 vue 组件。使用此功能,您可以将 Vue js 部分应用到现有的 rails 项目并开始编写现代 javascript 代码。