# 0429 tailwind 續, turbolinks, stimulus
###### tags: `Ruby / Rails`
- 課前叮嚀:有空看一下 jQuery 程式碼,會用到的功能大約 10 個
## tailwind 續
- [0426 筆記連結](https://hackmd.io/sezD14llTg6iAwa5L78W8A#Tailwind)
- [再一次官網連結](https://tailwindcss.com/docs/installation)
- 要在 postcss.config.js 裡加入
- module export
```javascript=
module.exports = {
plugins: {
require('tailwinds'),
require
}
}
```
```javascript=
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
```
`$ yarn install`
如果出現 `Error: PostCSS plugin tailwindcss requires PostCSS 8.`
[官網說明](https://tailwindcss.com/docs/installation#post-css-7-compatibility-build)
```shell=
## 移除原本安裝的錯誤版本
$ yarn remove tailwindcss postcss autoprefixer
## 使用他要求的版本
$ yarn add -D tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
```
### 自訂 tailwind 安裝的東西
- 如果把 tailwind 全部安裝起來要放一個 6MB 的資料在裡面
- 可以用 purge 指定需要的東西,有效減少資源使用
```javascript=
// tailwind.config.js
module.exports = {
purge: [
'./src/**/*.html',
'./src/**/*.js',
'app/views/**/*', // view裡所有的檔案
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {},
plugins: [],
}
```
日期套件
- 如果使用套件,裡面有使用 CSS 的話,要在指定 purge 時把用到的 CSS 也放進去,不然會出現問題
---
## turbolinks 補充
[參考文章-建議看過一次](https://www.writershelf.com/article/rails-turbolinks%E2%84%A2-5-%E6%B7%B1%E5%BA%A6%E7%A0%94%E7%A9%B6?locale=zh-TW)
rails 在建立連結時會使用 turbolinks
當使用者點擊連結時會觸發 turbolinks
xhr方式打過來 直接換掉頁面
透過turblinks 在做存取
缺少 DOMContentLoaded 的行為,所以後面跟著的 js 指令就不會被執行
## Stimulus
- [官網連結](https://stimulus.hotwire.dev/)
把網頁中特定區塊交給一個特定 js 控制
不用煩惱兩頁間變換的對應麻煩
* 示範
```htmlembedded=
<!--HTML from anywhere-->
<div data-controller="hello">
<input data-hello-target="name" type="text">
<button data-action="click->hello#greet">
Greet
</button>
<span data-hello-target="output">
</span>
</div>
```
```javascript=
// hello_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "name", "output" ]
greet() {
this.outputTarget.textContent =
`Hello, ${this.nameTarget.value}!`
}
}
```
安裝:
`$ rails webpacker:install:stimulus`
(可以使用 rails 檢查裡面所有指令)
```javascript=
// application.js
import 'icon/fontawesome' // 會去找這個資料夾裡面的 index
import '../frontend' // 會去找這個資料夾裡面的 index
import '../styles' // 會去找這個資料夾裡面的 index
import "controllers" // 會去找這個資料夾裡面的 index
```
```javascript=
// controllers/index.js
const context = require.context("controllers", true, /_controller\.js$/)
// 去找 _controller.js 結尾的東西
application.load(definitionsFromContext(context))
```
在需要使用的 html.erb 裡面加
```htmlembedded=
<h1 data-controller="pocket">
<%= @restaurant.title %>
<div id="like-btn"
data-id="<%= @restaurant.id %>"
data-pocket-target ="btn"
class="like-btn <%= 'like-btn-favorited' if user_signed_in? && current_user.like?(@restaurant) %>"></div>
</h1>
```
建立一個 controller 檔案
```javascript=
// pocket_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "btn" ]
add() {
console.log('hi')
}
connect() {
}
}
```
js 在類別裡面要使用其他類別方法的話要在設定時加上 this
ex.
```javascript=
class Cat {
constructor(n) {
this.n = n
}
a() {
this.b()
}
b() {
console.log('hi')
}
}
let c = new Cat
c.a() // 'hi'
```
link_tag
pack.tag
導入位置差異
layout/application 引入
javascript
assets pipeline vs webpack
將所有css 跟 js 各自打包成一包
flash 常用於通知、提示
flash[:notice] => 變成 redirect_to 裡面的參數 :notice
可以把要顯示出來的東西放到 layout 裡面 加入
```ruby=
<%= flash[:notice] %>
<%= :notice %> 等於上面那行
<%= 就是一個viewhelper %>
```
layout 裡面的東西也可以用 partial render
所以可以特別建立一個 _flash.html.erb 裡面建立 :notice 要使用的樣式
### 客製化事件
- Multiple Actions
在一個 data-action 放兩個事件
```javascript=
<input type="text" data-action="focus->field#highlight input->search#update">
```
- JavaScript CustomEvent
- 範例:
```javascript=
// add an appropriate event listener
obj.addEventListener("cat", function(e) { process(e.detail) });
// create and dispatch the event
var event = new CustomEvent("cat", {
detail: {
hazcheeseburger: true
}
});
obj.dispatchEvent(event);
```
### Stimulus 中預設的事件行為
所以 button 的事件如果是 `'click'` 可以被省略

### 聽廣播
[MDN - EventTarget.dispatchEvent()](https://developer.mozilla.org/zh-TW/docs/Web/API/EventTarget/dispatchEvent)
```javascript=
window.dispatchEvent()
```
未解決。。。
### n + 1 問題
查詢資料是很耗資源的
迴圈會發生n + 1
先全部一次再加上各自的次數(n)
面試題常問 n + 1
如何解決 使用`includes`這個寫法處理
撈資料時多撈一點(?)
uchef的範例就是在最一開始撈所有餐廳時連user一起撈
就可以從被撈出來的user裡撈資料
這樣就不用一筆一筆查
```ruby=
# /restaurants_controller.rb
def index
@restaurants = Restaurant.all.includes(:user)
# 直接連 user 一起拿出來,要使用時就不用一筆一筆拿
# 多一行 includes 就可以讓 n+1 變成 1+1
end
```
簡略的爬蟲說明 [nokogiri官網](https://nokogiri.org/) 的順序蠻清楚的
1. 先檢視看結構
1. 找到要找的class name
1. 然後使用nokogiri
require'nokogiri'
require'upen-url'
doc= ... HTML...~~~~~~ 換路徑
File.new('result.json', 'w')
strip可以把空白拿掉
---
### 題外話:
- Redux
- 應用程式狀態管理的開源 JS 工具(前端)
- 給 JavaScript 使用的可預測 state 容器(如果你正在尋找一個 WordPress 框架,請查看 Redux Framework)
- 全域物件
- 經常與 React 搭配運用,也可獨立使用
rails --tasks / rails -T
namespace do
desc ''
task :world do
...
end
end
先修教材的$2.13 應該就是在講這個 提供給有興趣的人自己去看2.13內容 因為我不是非常確定XD
任務相依性
rake 不知道什麼是環境這件事
task :close => :open do (先做 open 再做 close)
要用 rails 相關方法要先寫 task :update => ==:environment== do...
(引入環境變數才能拿到 model)
cron => 定時爬蟲
*8**