React.js
, Vue.js
, Angular.js
为近期很流行的框架,改变了前端生活圈的生态。不过除了这些主流框架以外,Basecamp出了一款基於Rails
的微型框架Stimulus
Stimulus为Basecamp出品的基於SSR框架,宗旨为Rails的後端工程师不用了解更多的Javascript概念而设计出来的框架。在 Rails 圈已经红了一段时间,而我自己本身,是听 Drifting Ruby 的课程才了解 Stimulus
目前Stimulus已经发展到 v2.0!它已经问世了一段时间,并且已经进行了1个大版本的更动。
首先我们使用以下指令安装框架
yarn add stimulus
Rails 进入点的撰写位置会放在 config/webpacker.yml
,
在 app/javascript/packs/application.js
中,我们可以看到许多被 require
进来的套件或资料夹,这些都是使用者请 webpack 帮忙编译与打包的东西。
我们在app/javascript/packs/application.js
写下import 'controllers'
,就可以读取controllers
资料夹里面的档案。
import "controllers"
import Rails from "@rails/ujs"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
Rails.start()
ActiveStorage.start()
在使用Stimulus
前,我们必须要了解Webpack
的使用。
Webpack 预设会先读取 index.js
的档案,所以我们会先在app/javascript
底下创建一个资料夹名controllers
,并且在app/javascript/controllers
创一个档案index.js
。假设我们要引入一个han_theme.scss
,我们可以在index.js
写下
import 'han_theme.scss';
Webpack 一层一层读取,首先由Layout写下javascript_include_tag
➡️ 读取app/javascript/packs/application.js
➡️ 读取 require("styles")
➡️ 读取 ./styles/index.js
➡️ 读取import '
han_theme.scss';
✅ Webpack 就会知道读取han_theme.scss
。
若我们使用 Stimulus,要在index.js
写下
// Load all the controllers within this directory and all subdirectories.
// Controller files must be named *_controller.js or *_controller.ts.
import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"
const application = Application.start()
// 动态读取结尾为 _controller 的档案
const context = require.context("controllers", true, /_controller\.(js|ts)$/)
application.load(definitionsFromContext(context))
接着开始要介绍 Stimulus
的基本用法。
Stimulus
一共有三个主体(引言出自Hotwire.dev)
字串
, 数字
, 阵列
...event.target
为同一角色)actions, which connect controller methods to DOM events using
data-action
attributestargets, which locate elements of significance within a controller
values, which read, write, and observe data attributes on the controller’s element
为了部落格列表使用Stimulus,我们先创建1档案:app/javascript/controllers/admin/blogs_controller.js
,并且在档案里头写下一段基本的用法
import { Controller } from 'stimulus';
export default class extends Controller {
connect() {
console.log('部落格列表')
}
}
Stimulus 是用Javascript
假物件导向的语法糖的语法写,但虽然如此,Rails
的精神就是惯例优於设定,除非真的很好奇,不然我们不需要懂其中的内涵。
import { Controller } from 'stimulus';
export default class extends Controller {
constructor() {
super();
// 自定义逻辑
}
connect() {
console.log('部落格列表')
}
}
之前做了一个破坏惯例的动作,在内部class
加入建构子Constructor
,之後便出现了问题。
connect()
为位於生命周期中的画面载入阶段。若重整画面後,就会马上执行connect()
方法。个人习惯在connect()
写下一段简单的console.log
,检查该页面是否执行Stimulus Code。
接着我们对画面进行改写
= title '部落格列表'
= tag.div data: { controller: 'admin--blogs' }
/ 卡片内容
= card do
/ ......
/ 弹跳视窗
= modal(id: 'new-blog-modal', confirm_wording: '送出文章',
confirm_form: 'new_modal', title: '新增文章') do
/ ......
最後呈现的结果如下 ⬇️
我们来实作官方首页的程序码吧!
= tag.div data: { controller: 'admin--blogs' }
/ Stimulus 卡片内容
= card do
= card_header(title: 'Stimulus')
= card_body do
= tag.input type: 'text', data: { 'admin--blogs-target': 'name' }
= button_tag '输出', type: 'button', data: { action: 'click->admin--blogs#greet' },
class: 'btn btn-primary mx-2'
= tag.span data: { 'admin--blogs-target': 'output' }
import { Controller } from 'stimulus';
export default class extends Controller {
static targets = [ "name", "output" ]
connect() {
console.log('部落格列表')
}
greet() {
this.outputTarget.textContent =
this.nameTarget.value === '' ? 'Hello, 输入框没有填入值' : `Hello, ${this.nameTarget.value}!`
}
}
我们将官方的范例稍微做改写,若没有值,则会回传输入框没有填入值
。操作完官网上的范例後,接下来我们讲讲admin--blogs
的命名规则怎麽来。
下列为官网提到的 controller 的命名规则,因此我们可以推敲,当我们把档案在javascript/controllers/admin/blogs_controller
,controller
的名称为admin--blogs
If your controller file is named… | its identifier will be… |
---|---|
clipboard_controller.js | clipboard |
date_picker_controller.js | date-picker |
users/list_item_controller.js | users--list-item |
local-time-controller.js | local-time |
接着我们再讲click->admin--blogs#greet
是什麽?
click->admin--blogs#greet
为点击动作时,触发admin--blogs
的 greet
动作,而这边可以省略成admin--blogs#greet
。
以下为官网提到的预设事件
Element | Default Event |
---|---|
a | click |
button | click |
form | submit |
input | input |
input type=submit | click |
select | change |
textarea | input |
若要实现getter
, setter
,我们可以使用value
作为两个值之间的媒介。
import { Controller } from 'stimulus';
export default class extends Controller {
static targets = [ "name", "output", "searchedContent"]
static values = { testId: Number }
connect() {
console.log('部落格列表')
this.testIdValue = 1
}
greet() {
this.testIdValue += 10
this.outputTarget.textContent =
this.nameTarget.value === '' ?
`Hello, 输入框没有填入值 ${this.testIdValue}` :
`Hello, ${this.nameTarget.value}! ${this.testIdValue}`
}
}
上述的例子为,将this.testIdValue
设定初始值=1
,并且每按一次,this.testIdValue
就会 +10
。
除了当作getter
,setter
外,还可以在画面上绑定Value。我们将指定 controller 的位置指定value
,并且在connect()
内部将值印出来
= tag.div data: { controller: 'admin--blogs', 'admin--blogs-view-id-value': 40 }
/! 内容
import { Controller } from 'stimulus';
export default class extends Controller {
static values = { viewId: Number }
connect() {
console.log('部落格列表')
console.log('this.viewIdValue', this.viewIdValue)
}
}
我们也可以带入Rails
物件进去,如params
等。
= tag.div data: { controller: 'admin--blogs',
'admin--blogs-view-id-value': 40,
'admin--blogs-reload_at-value': Time.current.strftime('%F %T') }
import { Controller } from 'stimulus';
export default class extends Controller {
static values = { viewId: Number, reloadAt: String }
connect() {
console.log('部落格列表')
console.log('this.viewIdValue', this.viewIdValue)
console.log('this.reloadAtValue', this.reloadAtValue)
}
}
Day26-28
为Stimulus
的系列文
Stimulus
的设定、三大元素target
, value
, action
。Stimulus
如何搭配Ajax
使用Datatable
这系列的文章,会需要比较熟悉Javascript
的基本用法,如果有什麽想询问的话,欢迎在下方的留言区联络。
>>: Day 14. 模板语法Template Syntax – 插值 Attribute、JavaScript 表达式
docker 可以控制 docker 的 daemon & container 所使用的 日志驱动 ...
小弟自开学後白天上课晚上上班,每天时间不多,进度比较缓慢,请多见谅 上篇将资料存至资料库,这篇要将资...
哈罗~ 今天来介绍隐写技术(Steganography)。 所谓的隐写术就是可以将资讯以明文/密文的...
前言 网路通讯协定就是为电脑进行资料交换而建立的规章或标准的集合。常用的有TCP/IP协定、HTTP...
俗话说得好:「工欲善其事,必先利其器」。 没有一个好用的文字编辑器,要如何轻松愉悦的写程序呢? 安...