Skip to content
Torsten Rüger edited this page Jan 15, 2018 · 4 revisions

Vue is lightweight, simple to understand, and doesn't try to take over your app. As such it is a very good fit to start making an existing Rails app more dynamic. This filter assumes that you either know Vue, or read up on it while reading this. We'll go through some of the examples that are mentioned in the vue docs.

Classes and methods

One of the main features of the vue filter is that it lets you structure the vue app or component as a ruby class. Instance methods of the class, become data members for Vue. The initialize method becomes the data() method in vue.

    class App < Vue
      el '#app'
      def initialize
        @message = 'Hello Vue! Ruby2Js here.'
      end
    end

becomes:

    var App = new Vue({
               el: "#app", 
             data: function() {
                 return {
                   message: "Hello Vue! Ruby2Js here."
                 }
             }})

App and components

For the above example to work, we had to derive from Vue class, and the class name became the js variable name. This works well for apps. But what if you want to write a Vue component.

The filter detects if your class has a render method, or a template definition.

    class FooBar<Vue
      def render
      end
    end
    var FooBar = Vue.component("foo-bar", {
        render: function($h) {
          return $h("span", [])
        }
      })
    class TodoItem <Vue
      template '<li>{{ todo.text }}</li>'
    end
    var TodoItem = Vue.component("todo-item", {
       template: '<li>{{ todo.text }}</li>'
      ...
      })

notice also how the class name becomes the variable name, as before, but also the component name in kebab-case (as per Vue convention)

Props (for components) work in a similar way, as if it were a class method:

    class TodoItem <Vue
      props [:message]  #OR
      props message: String  #OR
      props message: {type: String , required: false} 
    end

all transform into what you would expect.

Methods and computed values

In Vue you can use computed values. These are methods that take no argument and the return value is cached.

Vue lets you define methods, which may take arguments, but are not cached. They are still reactive though, which is great.

Ruby2js will sort instance methods, so that methods with arguments become vue methods, and methods without arguments become computed properties. Like this:

  class Todo < Vue
    options el: ".start"
    def initialize
      @arr = [1,2,3]
    end
    def calc_something(a,b)
      return a +b
    end
    def sum_of
      return  @arr.inject(0) { |sum , item | sum + item }
    end
  end
    const Todo = new Vue({
      el: ".manage_start",  
      data() {
        return {arr: [1, 2, 3]}
      },
      methods: {
        calc_something(a, b) {
         return a + b
         }
      },
      computed: {
        sum_of() {
          return this.$data.arr.reduce((sum, item) => sum + item, 0)
        }
      }
   })

And while this is really handy in 95% of the cases, sometimes you need methods without arguments, because they may return values that should not be cached (and cause weird bugs if they are). You can just defined the method with and argument that you don't use, which doesn't even have to be passed on invocation.

Vue Lifecycle and special

Vue let's you define lifecycle hooks. Eg when the method mounted is defined, it will be called when the component or app is mounted. The full list is on vue.js or https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter/vue.rb . When a method with this named is defined, it will be hoisted into the constructor, and not be part of the methods hash.

To call Vue dollar functions like $emit (for events) use the Vue class as receiver instead, so this.$emit(arg) becomes Vue.emit(arg)

Rendering

Vue can be used with templates and the template language, or component may define a render method and generate the dom directly. To this end Ruby2js lets you use wunderbar dsl.