Vue.js入門教程

螞蟻金服體驗技術部招人啦,前端開發專家,Node.js開發專家,歡迎投遞簡歷,長期有效。郵箱: chenglin.mcl@antfin.com,。

關于結緣的前端使用哪種框架,筆者之前有過Angular.js的開發經驗,在React.js和Vue.js之間徘徊了一陣子最終選擇了Vue,在我看來Vue和Angular有許多的共同點,在看Vue的文檔的時候有很熟悉的味道,但和React類似只關注View這一塊。Vue沒有像React那樣什么都放到js中,簡潔方便的api設計以及組件式開發是我選擇它的主要原因。

實現前端大抵有兩種思路,一個是由后端拼接頁面后返回完整的網頁,然后由瀏覽器渲染。另一種是由后端返回json之類的數據,然后由前端拼接數據進行展示,當然也可以兩者混搭。實現前后端分離是很多web開發人員的夢想,有興趣的可以看看Web系統開發構架再思考-前后端的完全分離

結緣前端打算使用Vue.js做成SPA(Single Page Application)的形式,即一個入口頁面,后續數據由后端Nodejs實現Restful風格的API調用,然后在前端呈現。使用Webpack作為前端工程解決方案解決資源管理,按需加載,實時更新等問題。本篇我們探索使用Vue.js實現結緣的登錄界面。

代碼

代碼放在結緣的前端工程中,Vue-jieyuan,歡迎star,issue

安裝部署Vue開發環境

為了方便大型應用的開發,尤大大開發了Vue-cli腳手架,提供了一系列的工具和庫,方便我們快速的進行開發,具體功能包括單文件 Vue 組件,熱加載,保存時檢查代碼,單元測試等,本質上和Express的express-generator是一樣的。

因為vue-cli依賴webpack,所以首先安裝webpack這個工具:

$ npm install -g webpack

關于webpack如果沒了解過可以看基于webpack搭建前端工程解決方案探索,然后安裝vue-cli:

$ npm install -g vue-cli

使用方法如下:

$ vue init webpack my-project
$ cd my-project
$ npm install
$ npm run dev

執行完成后在瀏覽器中localhost:8080查看。

尤大大目前提供了4套官方模板,如下:

  • browserify - A full-featured Browserify + vueify setup with hot-reload, linting & unit testing.
  • browserify-simple - A simple Browserify + vueify setup for quick prototyping.
  • webpack - A full-featured Webpack + vue-loader setup with hot reload, linting, testing & css extraction.
  • webpack-simple - A simple Webpack + vue-loader setup for quick prototyping.
    可以根據需求選擇即可。

在使用過程中遇到兩個問題,如果你也遇到了,可以在issues中查看。

學習ES6

由于vue-cli生成的文件中使用的是ES6的語法,而ES6是未來的趨勢,所以ES6必須一學,目前瀏覽器和Nodejs對ES6的支持程度不斷提高,不過要在所有的瀏覽器中使用es6代碼目前還不可行,不過babel可以幫你提前體驗新的語法而不需要等待瀏覽器支持。babel本質上是一個js的預編譯器,可以把es6程序編譯成es5,從而在支持ES5的環境中運行。

特地查了一下ES6和ES2016,ES2015的區別,實際上ES6===ES2015 < ES2016,由于ECMA委員會決定將標準每年一更,因此新推出的ES6被改名為ES2015,后面的標準將實行年制命名,如ES2016,ES2017...

學習ES6/ES2015可以參考如下資源

學習vue目前沒有足夠的教程可以幫我們快速了解如何構建我們的應用,所以只能一點點摸索,借鑒前人的經驗,所幸尤大大有個使用Vue開發的Hacker News Clone,我們可以從這里吸收開發經驗。另外Cnode社區也有個用Vue開發的客戶端Vue-cnodejs也很不錯。

這里首先簡要介紹一些Hacker News 客戶端中使用到的ES6特性:

箭頭函數 => 和this

=>是匿名函數的一種簡寫,即lamda表達式,格式為( 形參列表 ) => { 函數體 },使用箭頭函數,內部函數繼承了外圍作用域的this值,再也不用寫var that=this這種hack代碼了。直接上代碼看:

// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);

// Statement bodies
nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});

// Lexical this
var bob = {
  _name: "Bob",
  _friends: [],
  printFriends() {
    this._friends.forEach(f =>
      console.log(this._name + " knows " + f));
  }
};

模塊定義

在ES6之前js沒有一個統一的模塊定義方式,流行的定義方式有AMD,CommonJS等,而ES6從語言層面對定義模塊的方式進行了統一。

// lib/math.js
export function sum(x, y) {
  return x + y;
}
export var pi = 3.141593;

// app.js
import * as math from "lib/math";
alert("2π = " + math.sum(math.pi, math.pi));

// otherApp.js
import {sum, pi} from "lib/math";
alert("2π = " + sum(pi, pi));

export default(默認加載)和 export *(整體加載)為:

// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
    return Math.exp(x);
}

// app.js
import exp, {pi, e} from "lib/mathplusplus";
alert("2π = " + exp(pi, e));

默認加載的好處是我們不需要知道模塊所要加載的變量名或函數名,輸出時指定任意名字,且不需要大括號。更詳細的可以查看阮一峰老師的module一節

const 和 let

const即常量,一旦定義了即不可變。let是更好的var,由于js的設計缺陷,var變量的作用域是函數體的全部,還有變量提升等怪異特性,導致詭異的錯誤,極難定位bug。而let擁有塊級作用域,聲明的全局變量不是全局對象的屬性,形如for (let x...)的循環在每次迭代時都為x創建新的綁定.能用let盡量不用var,具體請看Is there any reason to use the “var” keyword in ES6?以及深入淺出ES6(十四):let和const

function f() {
  {
    let x;
    {
      // okay, block scoped name
      const x = "sneaky";
      // error, const
      x = "foo";
    }
    // okay, declared with `let`
    x = "bar";
    // error, already declared in block
    let x = "inner";
  }
}

promise

語言標準實現的異步編程解決方案:

function timeout(duration = 0) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, duration);
    })
}

var p = timeout(1000).then(() => {
    return timeout(2000);
}).then(() => {
    throw new Error("hmm");
}).catch(err => {
    return Promise.all([timeout(100), timeout(200)]);
})

關于Vue-cli的webpack模板的代碼風格

Vue-cli本身是一套技術選型,本身有作者自己的設計偏好在里面,例如模板默認是ES6的語法,使用ESLint進行代碼規范等。在我開始使用這個工具的過程中有兩個糾結的地方,一個是縮進,一個分號。

關于縮進

模板中默認代碼使用的2個空格進行縮進,這沒問題,問題是在ESLint的配置文件.eslintrc.js中寫死了indent的規則,于是各種縮進必須按照規范來,不然就會出現多處如下的錯誤

 error  indent  Expected indentation of 4 space characters but found 6
  /Users/Calvin/Develop/githubs/jieyuan/Vue-jieyuan/src/App.vue:35:7
        Hello,

用java習慣了,格式糟糕的話format一下就好了啊,然后各種查資料是用2個空格還是4個空格,可以看看知乎的這個回答為什么JS的規范說要用兩個空格來縮進?,恩,看來寫js代碼用2個空格更流行一些。如果你用sublime,那么可以打開你一個js文件然后Preference -> Settings More -> Syntax Specfic-User,然后寫入以下選項 :

{
  "tab_size": 2,
  "translate_tabs_to_spaces": true
}

同理對.vue也做一遍。不過蘿卜青菜各有所愛,只要同意規范就好,如果還是希望使用4空格,可以編輯.eslintrc.js的indet項。

關于寫不寫分號

習慣了寫分號,至今為止一直認為寫分號會讓代碼清晰,不容易出錯。不過在js這樣不強制寫分號的語言中需要另外考慮一番,可以看看知乎的這個問題:JavaScript 語句后應該加分號么?,于是又被尤大的答案折服了,ok,咱也不寫分號了。更多的還是建議看尤大給的鏈接semicolons

單文件組件以及Vue-loader解惑

看Vue-cli中的src/componets文件夾有個Hello.vue的文件,這個是默認生成的單文件組件。如下:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>
<script>
export default {
  data () {
    return {
      // note: changing this line won't causes changes
      // with hot-reload because the reloaded component
      // preserves its current state and we are modifying
      // its initial state.
      msg: 'Hello World!'
    }
  }
}
</script>

咦?不對啊,這玩意是組件?Vue文檔中不是說組件要用如下形式聲明嗎:

var MyComponent = Vue.extend({
  // options...
})

// Globally register the component with tag: my-component
Vue.component('my-component', MyComponent)
<div id="example">
  <my-component></my-component>
</div>

好吧,在Building Large-Scale Apps中文檔介紹了這種單文件的組件,它的特點是單文件組合HTML 模板,CSS和JS,并且可以使用自己想用的預處理器,并且css代碼對于每個組件是隔離的,只能說Vue,就決定是你了!,例如:

直接官網盜圖
,尤大創造了一個新的文件格式.vue,那這種文件咋解析啊,有沒有文件解析器?于是有了vue-loader,它的官方介紹如下:

vue-loader is a loader for Webpack that can transform Vue components written in the following format into a plain JavaScript module

恩,Vue-loader會自動幫你把這種單文件組件轉成組件使用,我們就不用操心啦。當然尤大也不強制你把代碼都放在一個文件里,可以拆開放:

<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>
或者從npm模塊加載:
<!-- import a file from the installed "todomvc-app-css" npm package -->
<style src="todomvc-app-css/index.css">

更多內容可以看Vue-loader的官方文檔,跟著做一遍可以加深印象,更了解webpack和vue的思想。

開發Vue組件

好吧,說了那么多,我們來開發一個基本的Login組件吧。目前網頁設計水平還跟不上,直接使用Bootstrap的css庫,在index.html的head標簽中加入

<link rel="stylesheet" >

compoents標簽中添加Login.vue文件,輸入如下內容:

<template>
<!-- Stack the columns on mobile by making one full-width and the other half-width -->
    <div class="container">
      <form class="form-signin">
        <h2 class="form-signin-heading">{{title}}</h2>
        <label for="inputEmail" class="sr-only">郵件地址</label>
        <input type="email" id="inputEmail" class="form-control" placeholder="郵件地址" required autofocus>
        <label for="inputPassword" class="sr-only">密碼</label>
        <input type="password" id="inputPassword" class="form-control" placeholder="密碼" required>
        <div class="checkbox">
          <label>
            <input type="checkbox" value="remember-me"> 記住我
          </label>
        </div>
        <button class="btn btn-lg btn-primary btn-block" type="submit">登錄</button>
      </form>
    </div>

</template>

<script>
export default {
  data () {
    return {
      // note: changing this line won't causes changes
      // with hot-reload because the reloaded component
      // preserves its current state and we are modifying
      // its initial state.
      title: '登錄結緣'
    }
  }
}
</script>

<style >
  body {
  padding-top: 40px;
  padding-bottom: 40px;
  background-color: #eee;
}

.form-signin {
  max-width: 330px;
  padding: 15px;
  margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
  margin-bottom: 10px;
}
.form-signin .checkbox {
  font-weight: normal;
}
.form-signin .form-control {
  position: relative;
  height: auto;
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
  padding: 10px;
  font-size: 16px;
}
.form-signin .form-control:focus {
  z-index: 2;
}
.form-signin input[type="email"] {
  margin-bottom: -1px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
  margin-bottom: 10px;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
</style>

App.vue中的Hello組件換成Login組件即可,最終效果如下:

代碼

代碼放在結緣的前端工程中,Vue-jieyuan,歡迎star,issue

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容