1 分鐘閱讀

1. 首先先建立一個vue101的專案

rails new vue101 -T

2. 加入vue套件 (這步驟可以改用現成的gem vuejs-rails)

  • vue.jsvue-resource.js放進/vendor/assets/javascript/中 (vue-resource是Vue處理JSONP web requests的plugin,這邊的範例需要用到)

  • 把他們require進來

// [path] app/assets/javascript/application.js
//= require vue
//= require vue-resource

3. 拿掉turbolinks這個gem (會跟vue衝到)

  • 其實只要從首頁拿掉他的載入參數即可
<%= javascript_include_tag 'application' %>
  • 並且要把這行移至</body>前 (放在head是無法work的)

4. 參考vue官網的todolist範例,這邊也使用rails scaffold建立一個todolist來對照

  • vue官網的Todo範例 點我看範例

  • 建立一個Todo的scaffold,有一個text的欄位

rails g scaffold Todo text:string
rake db:migrate

-方便測試,這邊把route加到首頁

# [path] route.rb
  root 'todo#index'
  resources :todos

5. 改用js取代coffee

  • 因為用js比較方便,所以…就換掉吧 (可以參考這篇)
# [path] config/applicatioin.rb
config.generators.javascript_engine :js

6. 把Vue範例部分放進來

  • 把網頁部分放到post的index.html.erb下方
<!-- [path] app/views/todos/index.html.erb -->
(...上略)
<hr>
<div id="app">
  <input v-model="newTodo" v-on:keyup.enter="addTodo">
  <ul>
    <li v-for="todo in todos">
      <span></span>
      <button v-on:click="removeTodo($index)">X</button>
    </li>
  </ul>
</div>
  • 把js部分放到對應的post.js
// [path] app/assets/javascripts/todos.js
new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todos: [
      { text: 'Add some todos' }
    ]
  },
  methods: {
    addTodo: function () {
      var text = this.newTodo.trim()
      if (text) {
        this.todos.push({ text: text })
        this.newTodo = ''
      }
    },
    removeTodo: function (index) {
      this.todos.splice(index, 1)
    }
  }
})
  • 可以先確認一下Vue部分有沒有work

7.CRUD實作 - 前置

  • 這邊需要做一個前置動作,因為rails會有csrf taken的機制,因此再送出表單時需要特別在header加入token,這邊直接統一加在application.js中,之後就不用分別在每次的request加入了
// [path] app/assets/javascripts/application.js
Vue.http.headers.common['X-CSRF-TOKEN'] = $('meta[name="csrf-token"]').attr('content');

8.CRUD實作 - 清單頁

// [path] app/assets/javascripts/todos.js
new Vue({
(...)
  created: function() {
      this.fetchTodos();
  },
  methods: {
    fetchTodos: function(){
      this.$http.get('posts').then(function(response){
        this.todos = response.data;
      });
    },
(...)
  • 可以看到$http.get('todos'),表示用get方式送至http://localhost:3000/todos/並回傳結果到response,執行function(response){}中的項目
  • $http用法可以參考vue-resource的說明
  • 所以現在我們知道,要到todo#index中,寫回傳js會做的事情,這邊將@todos以json方式丟出 (其實不寫也可以他會自動腦補@todo是要回傳的值,如果今天要回傳@list就一定要寫)
# [path] app/controllers/todos_controller.rb
def index
 @todos = Todo.all

    respond_to do |format|
      format.html
      format.json { render json: @todos }
    end
end
  • 因此在response.data中,就可以收到

9.CRUD實作 - 新增

  • 這邊將新增做調整,加入ajax回寫
// [path] app/assets/javascripts/todos.js
(...)
    addTodo: function () {
      var text = this.newTodo.trim()
      if (text) {
        this.$http.post('posts', {title: title}).then(function(response){
          this.todos.push({ title: title, id: response.data.id })
          this.newTodo = ''
        });
      }
    },
(...)

10.CRUD實作 - 刪除

  • 刪除比較麻煩一點,因為後端要對應id,但是前端splice是要看index,因此我調整為兩個參數傳入
// [path] app/assets/javascripts/todos.js
(...)
    removeTodo: function (index, todo) {
      this.$http.delete('todos/'+todo.id).then(function(response){
        this.todos.splice(index, 1)
      });
    }
(...)
  • 因為改兩個參數傳入,template也要同步調整
<!-- [path] app/views/todos/index.html.erb -->
    <li v-for="todo in todos">
      <span></span>
      <button v-on:click="removeTodo($index, todo)">X</button>
    </li>

11.CRUD實作 - 編輯

  • 接下來就開始亂寫了

直接看github吧 Vue101

參考

  1. Vue Plugin說明
  2. http://hsuancheng.net/programming/2016/05/17/vue-js-on-rails/

標籤: ,

分類:

更新時間:

留言