最近有點想學點不同的東西, 因此想嘗試 vue.js.
在 survey 的過程中發現了 pug 這個東西, 和 ruby 的 slim 類似. 以前在寫 react 的過程中, 我認為最討厭的一點就是寫 jsx 了, 一不小心就會寫得很長, 再加上基本上都會寫在 render
方法中, 換行和縮排就會花費不少空間, 大概像這樣:
class MyComponent extends React.PureComponent {
render () {
return (
<div>Hello</div>
)
}
}
當然現在可以寫成純函數的形式的確是比較精簡了, 但還是不喜歡, 長期以來也都沒找到什麼解決辦法, 但是現在有了, 可以使用 babel-plugin-transform-react-pug 在 render
的時候使用 pug 的語法, 應該能舒服許多.
不過本文的重點不是這個, 因為其實我是先想玩看看 vue.js, 接著看到 vue.js 中可以那樣寫才知道現在有這樣的東西, 所以還沒有嘗試 babel-plugin-transform-react-pug:
<template lang="pug">
#app
p {{ message }}
</template>
<script>
export default {
data: function () {
return {
message: "Hello Vue!"
}
}
}
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>
那麼首先先跑個
rails webpacker:install:vue
它會提供所有基本的設定和一個簡單的範例 (類似上面的), 還會有一則訊息提醒你要記得修改 config/initializers/content_security_policy.rb .
但是這樣還不夠. 根據 packs/hello_vue.js 內所述, 如果有使用 Turbolinks, 需要再額外安裝:
yarn add vue-turbolinks
然後照裡面所寫的, 將相關程式碼複製到 packs/application.js:
import TurbolinksAdapter from 'vue-turbolinks'
import Vue from 'vue/dist/vue.esm'
import App from '../app.vue'
Vue.use(TurbolinksAdapter)
document.addEventListener('turbolinks:load', () => {
new Vue({
el: '#hello',
data: () => {
return {
message: "Can you say hello?"
}
},
components: { App }
})
})
然後在頁面中插入 <div id="hello"><app /></div>
就可以看到大大的 Hello Vue! 了.
打開 app.vue 以後會看到:
<template>
<div id="app">
<p>{{ message }}</p>
</div>
</template>
但是我想要:
<template lang="pug">
#app
p {{ message }}
</template>
但只是想要是沒有用的, 必須讓 webpack 認得 pug 並且編譯成該有的樣子才行, 因此來安裝這些套件:
yarn add pug pug-plain-loader
然後建立一個 config/webpack/loaders/pug.js:
module.exports = {
test: /\.pug(\.erb)?$/,
use: [{
loader: 'pug-plain-loader'
}]
}
並且修改 config/webpack/environment.js:
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')
const pug = require('./loaders/pug')
environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.loaders.prepend('pug', pug)
module.exports = environment
這個時候內含 pug template 的 app.vue 就能正確的被編譯了.
再來有個要求是, 我希望能把檔案都放在 components 目錄中, 有新元件就自動載入命名註冊, 我的做法是, 建立一個 components/index.js:
import Vue from 'vue/dist/vue.esm'
const req = require.context('components', true, /\.vue$/)
function capitalize (word) {
return word.charAt(0).toUpperCase() + word.substring(1)
}
function titleize (words) {
return words.match(/\w+/g).map(capitalize).join('')
}
function constantize (filename) {
return titleize(filename.match(/^(?:\.\/)?(.+)(?:\.vue$)$/)[1])
}
req.keys().map(key => Vue.component(constantize(key), req(key).default))
然後修改一下 packs/application.js:
import TurbolinksAdapter from 'vue-turbolinks'
import Vue from 'vue/dist/vue.esm'
import 'components'
Vue.use(TurbolinksAdapter)
document.addEventListener('turbolinks:load', () => {
new Vue({ el: '#app' })
})
然後把 #app
放在 body
下, 這樣的設置看起來似乎一切都完美了…