git clone從https://github.com/chentianwei411/at-mentions-with-action-textjavascript
先fork下來,而後拷貝https鏈接,最後在terminal上:html
git clone https://github.com/chenwei/at-mentions-with-action-text.gitjava
而後由於ruby 和 rails版本。使用命令:webpack
rvm 2.6.1@railsXXX版本 #簡單的集合命令,詳細看以前的相關博客。
根據提示安裝bundler和yarn更新。git
10821 gem install bundler:2.0.1
10822 bundle update
10828 yarn install --check-files
最後rails db:migrate並rails s啓動服務器localhost:3000github
# config.application_name = Rails.application.class.parent_name config.application_name = Rails.application.class.module_parent_name
使用tribute庫來實現@mention功能,支持Vue。web
參考https://zurb.github.io/tribute/example/案例,在輸入框輸入@能夠顯示人名的下拉列表。數據庫
trix文本編輯器已經被集成到新版本。json
使用stimulus.js增長JavaScript腳本。api
rails webpacker:install:stimulus
而後下載ZURB tribute javascript library。這裏使用yarn,也能夠用gem 'tribute'
https://github.com/zurb/tribute
這是用ES6寫的@mention引擎。無需依賴dependencies。跨瀏覽器。
yarn add tributejs
resources :mentions, only: [:index]
目的是點擊這個url來自動獲取users。而後就能夠動態地load. json格式的user數據。👇
class MentionsController < ApplicationController def index @users = User.all respond_to do |format| format.json end end end
⚠️,演示是取所有的user,實際上線版本只取通常前10個用戶名字。
json.array! @users, partial: "users/users", as: :user
獲得一個array of users, 而後返回partial, 數據名字是user。
#從user提取它們的id , name json.extract! user, :id, :name
json.sgid user.attachable_sgid
json.content render(partial: "users/user", locals: {user: user}, format: [:html])
解釋:
1. json.sgid user.attachable_sgid
須要在modles/User.rb內include一個模塊,以便使用方便的方法, 👆的user.attachable_sgid。
include ActionText::Attachable
2. json.conent。 渲染views/users/_user.html.erb,傳入數據user,格式是html。
<span class="mention"> <%= image_tag gravatar_image_url(user.email, size: 40), height: 20, width: 20, class: "rounded" %> <%= user.name %> </span>
即便用Stimulus的data-target來取這個元素。
<div class="form-group"> <%= form.label :body %> <%= form.rich_text_area :body, class: 'form-control', data: { controller: "mentions", target: "mentions.field" } %> </div>
import { Controller } from 'stimulus' export default class extends Controller { static targets = ["field"] #定位到post視圖的元素上。 contect() {
this.editor = this.fieldTarget.editor
this.initializeTribute() #初始化tribute
}
initializeTribute() {
...
} }
爲了使用Tribute須要import
...
import Tribute from 'tributejs' import Trix from 'trix'
...
initializeTribute() { this.tribute = new Tribute({ allowSpaces: true, #集合中的方法,能夠在mentions中有空格 lookup: 'name', #集合中的方法,在對象中搜索對應的column(函數或字符串) values: this.fetchUsers, #必須的(required)經過異步函數得到一個數組對象,用於匹配。 })
this.tribute.attach(this.fieldTarget) #把tribute實例鏈接到元素上。
... }
異步函數:fetchUsers
fetchUsers(text, callback) { fetch(`/mentions.json?query=${text}`) .then(response => response.json()) .then(users => callback(users)) .catch(error => callback([])) }
當不須要監聽事件了用disconnect來從元素上移除Tribute實例:
disconnect() {
this.tribute.detach(this.fieldTarget)
}
在initializeTribute()函數內添加
// 點擊後回退一個字符,即去掉@: this.tribute.range.pasteHtml = this._pasteHtml.bind(this) // 給目標元素添加事件,當完成 this.fieldTarget.addEventListener("tribute-replaced", this.replaced)
添加函數replaced:
這裏要參考Trix api文檔:https://github.com/basecamp/trix
replaced(e) { console.log(e) // 獲得事件中的數據 let mention = e.detail.item.original // 建立Trix.Attachment,而後調用insertAttachment方法來插入HTML let attachment = new Trix.Attachment({ sgid: mention.sgid, content: mention.content }) this.editor.insertAttachment(attachment) // 再插入一個空格,具體見Trix Api. this.editor.insertString(" ") }
添加_pasteHtml函數:
_pasteHtml(html, startPos, endPos) { let position = this.editor.getPosition() //2個Trix方法 this.editor.setSelectedRange([position - endPos, position]) this.editor.deleteInDirection("backward") }
一個bug: post更新後,再次編輯,@mention內容不可見。當前解決方法是在user.rb添加:
def to_trix_content_attachment_partial_path
to_partial_path
end