Vue.js 是一款極簡的 mvvm 框架,若是讓我用一個詞來形容它,就是 「輕·巧」 。若是用一句話來描述它,它可以集衆多優秀逐流的前端框架之大成,但同時保持簡單易用。廢話很少說,來看幾個例子:javascript
<script src="vue.js"></script> <div id="demo"> {{message}} <input v-model="message"> </div> <script> var vm = new Vue({ el: '#demo', data: { message: 'Hello Vue.js!' } }) </script>
首先,代碼分兩部分,一部分是 html,同時也是視圖模板,裏面包含一個值爲 message
的文本何一個相同值的輸入框;另外一部分是 script,它建立了一個 vm 對象,其中綁定的 dom 結點是 #demo
,綁定的數據是 {message: 'Hello Vue.js'}
,最終頁面的顯示效果就是一段 Hello Vue.js
文本加一個含相同文字的輸入框,更關鍵的是,因爲數據是雙向綁定的,因此咱們修改文本框內文本的同時,第一段文本和被綁定的數據的 message
字段的值都會同步更新——而這底層的複雜邏輯,Vue.js 已經所有幫你作好了。css
咱們還能夠加入更多的 directive,好比:html
<script src="vue.js"></script> <div id="demo2"> <img title="{{name}}" alt="{{name}}" v-attr="src: url"> <input v-model="name"> <input v-model="url"> </div> <script> var vm = new Vue({ el: '#demo2', data: { name: 'taobao', url: 'https://www.taobao.com/favicon.ico' } }) </script>
這裏的視圖模板加入了一個 <img>
標籤,同時咱們看到了 2 個特性的值都寫做了 。這樣的話,圖片的
title
和 alt
特性值就都會被綁定爲字符串 'taobao'
。前端
若是想綁定的特性是像 img[src]
這樣的不能在 html 中隨意初始化的 (可能默認會產生預期外的網絡請求),不要緊,有 v-attr="src: url"
這樣的寫法,把被綁定的數據裏的 url
同步過來。vue
沒有介紹到的功能還有不少,推薦你們來我(發起並)翻譯的Vue.js 中文文檔java
最後要介紹 Vue.js 對於 web 組件化開發的思考和設計node
若是咱們要開發更大型的網頁或 web 應用,web 組件化的思惟是很是重要的,這也是今天整個前端社區長久不衰的話題。webpack
Vue.js 設計了一個 *.vue
格式的文件,令每個組件的樣式、模板和腳本集合成了一整個文件, 每一個文件就是一個組件,同時還包含了組件之間的依賴關係,麻雀雖小五臟俱全,整個組件從外觀到結構到特性再到依賴關係都盡收眼底 :git
而且支持預編譯各類方言:github
這樣再大的系統、在複雜的界面,也能夠用這樣的方式庖丁解牛。固然這種組件的寫法是須要編譯工具才能最終在瀏覽器端工做的,下面會提到一個基於 webpack 的具體方案。
從功能角度,template, directive, data-binding, components 各類實用功能都齊全,而 filter, computed var, var watcher, custom event 這樣的高級功能也都洋溢着做者的巧思;從開發體驗角度,這些設計幾乎是徹底天然的,沒有刻意設計過或欠考慮的感受,只有個別不得已的地方帶了本身框架專屬的 v-
前綴。從性能、體積角度評估,Vue.js 也很是有競爭力!
webpack 是另外一個近期發現的好東西。它主要的用途是經過 CommonJS 的語法把全部瀏覽器端須要發佈的靜態資源作相應的準備,好比資源的合併和打包。
舉個例子,如今有個腳本主文件 app.js
依賴了另外一個腳本 module.js
// app.js var module = require('./module.js') ... module.x ... // module.js exports.x = ...
則經過 webpack app.js bundle.js
命令,能夠把 app.js
和 module.js
打包在一塊兒並保存到 bundle.js
同時 webpack 提供了強大的 loader 機制和 plugin 機制,loader 機制支持載入各類各樣的靜態資源,不僅是 js 腳本、連 html, css, images 等各類資源都有相應的 loader 來作依賴管理和打包;而 plugin 則能夠對整個 webpack 的流程進行必定的控制。
好比在安裝並配置了 css-loader 和 style-loader 以後,就能夠經過 require('./bootstrap.css')
這樣的方式給網頁載入一份樣式表。很是方便。
webpack 背後的原理其實就是把全部的非 js 資源都轉換成 js (如把一個 css 文件轉換成「建立一個 style
標籤並把它插入 document
」的腳本、把圖片轉換成一個圖片地址的 js 變量或 base64 編碼等),而後用 CommonJS 的機制管理起來。一開始對於這種技術形態我我的仍是不太喜歡的,不過隨着不斷的實踐和體驗,也逐漸習慣並認同了。
最後,對於以前提到的 Vue.js,做者也提供了一個叫作 vue-loader 的 npm 包,能夠把 *.vue
文件轉換成 webpack 包,和整個打包過程融合起來。因此有了 Vue.js、webpack 和 vue-loader,咱們天然就能夠把它們組合在一塊兒試試看!
回到正題。今天要分享的是,是基於上面兩個東西:Vue.js 和 webpack,以及把它們串聯起來的 vue-loader
Vue.js 的做者以及提供了一個基於它們三者的項目示例 (連接已失效)。而咱們的例子會更貼近實際工做的場景,同時和團隊以前總結出來的項目特色和項目流程相吻合。
<components>
組件目錄,一個組件一個 .vue
文件
a.vue
b.vue
<lib>
若是實在有不能算組件,但也不來自外部 (tnpm) 的代碼,能夠放在這裏
foo.css
bar.js
<src>
主應用/頁面相關文件
app.html
主 htmlapp.vue
主 vueapp.js
一般作的事情只是 var Vue = require('vue'); new Vue(require('./app.vue'))
<dist>
(ignored)<node_modules>
(ignored)gulpfile.js
設計項目打包/監聽等任務package.json
記錄項目基本信息,包括模塊依賴關係README.md
項目基本介紹經過 gulpfile.js
咱們能夠設計整套基於 webpack 的打包/監聽/調試的任務
在 gulp-webpack 包的官方文檔裏推薦的寫法是這樣的:
var gulp = require('gulp'); var webpack = require('gulp-webpack'); var named = require('vinyl-named'); gulp.task('default', function() { return gulp.src(['src/app.js', 'test/test.js']) .pipe(named()) .pipe(webpack()) .pipe(gulp.dest('dist/')); });
咱們對這個文件稍加修改,首先加入 vue-loader
tnpm install vue-loader --save .pipe(webpack({ module: { loaders: [ { test: /\.vue$/, loader: 'vue'} ] } }))
其次,把要打包的文件列表從 gulp.src(...)
中抽出來,方便未來維護,也有機會把這個信息共享到別的任務
var appList = ['main', 'sub1', 'sub2'] gulp.task('default', function() { return gulp.src(mapFiles(appList, 'js')) ... }) /** * @private */ function mapFiles(list, extname) { return list.map(function (app) {return 'src/' + app + '.' + extname}) }
如今運行 gulp
命令,相應的文件應該就打包好並生成在了 dist
目錄下。而後咱們在 src/*.html
中加入對這些生成好的 js
文件的引入:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Main</title> </head> <body> <div id="app"></div> <script src="../dist/main.js"></script> </body> </html>
用瀏覽器打開 src/main.html
這時頁面已經能夠正常工做了
監聽更加簡單,只要在剛纔 webpack(opt)
的參數中加入 watch: true
就能夠了。
.pipe(webpack({ module: { loaders: [ { test: /\.vue$/, loader: 'vue'} ] }, watch: true }))
固然最好把打包和監聽設計成兩個任務,分別起名爲 bundle
和 watch
:
gulp.task('bundle', function() { return gulp.src(mapFiles(appList, 'js')) .pipe(named()) .pipe(webpack(getConfig())) .pipe(gulp.dest('dist/')) }) gulp.task('watch', function() { return gulp.src(mapFiles(appList, 'js')) .pipe(named()) .pipe(webpack(getConfig({watch: true}))) .pipe(gulp.dest('dist/')) }) /** * @private */ function getConfig(opt) { var config = { module: { loaders: [ { test: /\.vue$/, loader: 'vue'} ] } } if (!opt) { return config } for (var i in opt) { config[i] = opt } return config }
如今你能夠沒必要每次修改文件以後都運行 gulp bundle
才能看到最新的效果,每次改動以後直接刷新瀏覽器便可。
打包好的代碼已經不那麼易讀了,直接在這樣的代碼上調試仍是不那麼方便的。這個時候,webpack + vue 有另一個現成的東西:source map 支持。爲 webpack 加入這個配置字段 devtool: 'source-map'
:
var config = {
module: {
loaders: [
{ test: /.vue$/, loader: ‘vue’}
]
},
devtool: ‘source-map’
}
再次運行 gulp bundle
或 gulp watch
試試看,是否是開發者工具裏 debug 的時候,能夠追蹤斷點到源代碼了呢:)
完整的 javascript 代碼以下:
var gulp = require('gulp') var webpack = require('gulp-webpack') var named = require('vinyl-named') var appList = ['main'] gulp.task('default', ['bundle'], function() { console.log('done') }) gulp.task('bundle', function() { return gulp.src(mapFiles(appList, 'js')) .pipe(named()) .pipe(webpack(getConfig())) .pipe(gulp.dest('dist/')) }) gulp.task('watch', function() { return gulp.src(mapFiles(appList, 'js')) .pipe(named()) .pipe(webpack(getConfig({watch: true}))) .pipe(gulp.dest('dist/')) }) /** * @private */ function getConfig(opt) { var config = { module: { loaders: [ { test: /\.vue$/, loader: 'vue'} ] }, devtool: 'source-map' } if (!opt) { return config } for (var i in opt) { config[i] = opt[i] } return config } /** * @private */ function mapFiles(list, extname) { return list.map(function (app) {return 'src/' + app + '.' + extname}) }
作出一個 vue + webpack 的 generator,把這樣的項目體驗分享給更多的人。目前我基於團隊內部在使用的輕量級腳手架工具寫了一份名叫 just-vue
的 generator,目前這個 generator 還在小範圍試用當中,待比較成熟以後,再分享出來
其實上面提到的 just-vue
腳手架已經遠不止文章中介紹的東西了, 咱們在業務落地的「最後一千米」作了更多的沉澱和積累,好比自動圖片上傳與畫質處理、rem單位自動換算、服務端/客戶端/數據埋點接口的梳理與整合、自動化 htmlone 打包與 awp 發佈等等。它們爲支持業務的開發者提供了更簡單高效的工做體驗。 篇幅有限,更多內容我也但願未來有機會再多分享出來。
最後再次但願你們若是有興趣的話能夠來玩一下,無線前端組內的同窗我都願意提供一對一入門指導:)
Just Vue!