# 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'` 可以被省略 ![](https://i.imgur.com/VzQ5Ikr.png) ### 聽廣播 [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**