Vue 的官方文檔寫的很是棒(另外一個我以爲中文文檔寫的很好地是 Ant-Design)。
這篇文章以使用 vue-cli
生成的項目爲基礎,以完整 demo
的形式講解 Vue
的基礎語法。關於 vue-cli
生成項目的講解,能夠參考:vue-cli 構建 vue 項目詳解 。javascript
在 vue-cli
生成的項目中,咱們打開 src/components
文件夾下 HelloWorld.vue
組件,爲便於演示,刪減了一部份內容(本文中的例子都將改造 HelloWorld.vue
組件來演示 Vue
語法):css
<template> <div class='hello'> <h1>{{ msg }}</h1> <h2>Essential Links</h2> </div> </template> <script> export default { name: 'HelloWorld', data() { return { msg: 'Welcome to Your Vue.js App', }; }, }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } </style>
<!-- more -->html
在
vue
中,有好幾種方式用來建立組件,後面會單獨寫一篇文章來介紹。
HelloWord.vue
文件中的內容分爲三個部分:前端
<template> ... </template> <script> ... </script> <style> ... </style>
分別在這三類標籤裏面寫入結構、腳本、樣式。 這個文件以 .vue
結尾(注意:其餘建立組件方式是以 .js
結尾),這是 vue
中建立組件的一種方式:單文件組件。換句話說就是每一個 .vue
文件就是一個組件。vue
有一點須要注意:template
只能容許一個子元素。java
如今的文件中,是在路由 router/index.js
中引入的 HelloWorld
組件:react
import Vue from 'vue'; import Router from 'vue-router'; import HelloWorld from '@/components/HelloWorld'; Vue.use(Router); export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld, }, ], });
引入的方式一目瞭然,再也不贅述。那如何在組件中引入組件呢?下面咱們在 App
組件中直接引入 Helloworld
看看:git
<template> <div id='app'> <img src='./assets/logo.png'> <HelloWorld/> </div> </template> <script> import HelloWorld from './components/HelloWorld'; export default { name: 'App', components: { HelloWorld }, }; </script> <style> #app { text-align: center; color: #2c3e50; margin-top: 60px; } </style>
在 script
標籤中,HelloWorld
組件被引入並添加到 components
屬性中。這樣,就在 App
組件中引入了 HelloWorld
組件。啓動項目在瀏覽器中打開,會看到 App
組件中的內容:Vue
的 Logo
、 HelloWorld
組件裏的內容。github
那若是要引入多個組件該怎麼寫呢?假設咱們再有個 Demo
組件:vue-router
<template> <div id='app'> <img src='./assets/logo.png'> <hello-world/> <demo/> </div> </template> <script> import HelloWorld from './components/HelloWorld'; import Demo from './components/Demo'; export default { name: 'App', components: { 'hello-world': HelloWorld, demo: Demo, }, }; </script>
在 components
對象中定義多個屬性,指向引入的組件便可。
Vue
插值最多見的形式就是使用雙大括號 {% raw %}{{ }} {% endraw %}
的文本插值。在文章開頭中的 HelloWorld
組件中就使用了插值的方式實現數據綁定。這裏咱們詳細介紹一下:
在 Vue
組件中,都有一個 data
屬性,data
必須是一個函數,該函數的返回值是一個對象。咱們能夠在 template
中經過雙大括號來讀取 data
中的屬性值:
<template> <div> <h1>{{ msg }}</h1> <span v-once>這個將不會改變: {{ msg }}</span> </div> </template> <script> export default { // ... data() { return { msg: 'Welcome to Your Vue.js App', }; }, }; </script>
這裏也經過使用 v-once 指令(下面咱們要說),執行一次性地插值:當數據改變時,插值處的內容不會更新。可是要注意一次性插值會影響到該節點上的其它數據綁定。
如何在 template
中包裹的標籤的屬性上插值呢?假設咱們有一個 <button>
,想經過插值的方式設置它的 disable
屬性,須要這樣作:
<template> <div> // ... <button v-bind:disabled='btnState'>{{ name }}</button> </div> </template> <script> export default { // ... data() { return { name: 'Vue', btnState: true, // Add this }; }, }; </script>
在屬性中插值,須要經過字符串的形式讀取 data
中的值,不可使用雙大括號。如今,這個 button
就被 disable
掉了。
vue
中也支持表達式插值:
<template> <div> <!-- Add this --> {{ btnState ? 'The button is disabled' : 'The button is active'}} <button v-bind:disabled='btnState'>{{ name }}</button> </div> </template>
用雙大括號將表達式括起來。此時頁面上會顯示:The button is disabled
。固然,你能夠表達式中添加更加複雜的邏輯。
指令 (Directives
) 是帶有 v-
前綴的特殊特性。它的做用是什麼呢?就是當表達式的值改變時,將其產生的連帶影響,響應式地做用於 DOM
。咱們看看幾個例子:
v-for
:<tamplate> <div> <ul> <li v-for='todo in todos' :key='todo.key'>{{ todo.text }}</li> </ul> </div> </tamplate> <script> export default { // ... data() { return { todos: [ { text: '學習 JavaScript' }, { text: '學習 Vue' }, { text: '學習 前端' }, ], }; }, }; </script>
v-for
指令能夠綁定數組的數據來渲染一個項目列表:
· 學習 JavaScript · 學習 Vue · 學習 前端
v-if
和 v-else
:<tamplate> <div> <ul> <li v-for='todo in todos' :key='todo.key'>{{ todo.text }}</li> </ul> // add this <p v-if='todos.length >= 1'>You have more than 1 todo</p> <p v-else>You have no todos</p> </div> </tamplate>
這裏,v-if
指令將根據表達式的值的真假來插入/移除 <p>
元素。
關於更多 vue
指令,能夠查看 vue 指令 api,這裏再也不一一講述。
vue
中能夠用 v-on
指令監聽 DOM
事件,並在觸發時運行相關 JavaScript
代碼。咱們經過幾個例子來看看 vue
中的事件處理。
<template> <div> <span>{{ counter }}</span> <button v-on:click='counter += 1'>+ 1</button> </div> </template> <script> export default { name: 'HelloWorld', data() { return { counter: 0, }; }, }; </script>
點擊 button
, 計數器遞增 +1
。+1
的邏輯寫在了 v-on
指令裏面,顯然這是不可取的,許多事件處理邏輯會更爲複雜。
在 Vue
組件中,都有一個 data
屬性,也有一個 methods
屬性。該屬性是一個對象,咱們能夠在對象中定義方法。對於上面的例子,咱們能夠把點擊 button
以後的處理邏輯放在 methods
中,click
事件調用 methods
中的方法:
<template> <div> <span>{{ counter }}</span> <button v-on:click='add'>+ 1</button> </div> </template> <script> export default { name: 'HelloWorld', data() { return { counter: 0, }; }, methods: { add() { this.counter += 1; }, }, }; </script>
在事件處理程序中調用 event.preventDefault()
或 event.stopPropagation()
是很是常見的需求。雖然咱們能夠在事件的響應函數裏面來作這些事情,可是 vue
提供了一個更優雅的方式來實現它 —— 事件修飾符,保證了事件處理函數的乾淨純粹:只關注數據處理邏輯。
修飾符是由點開頭的指令後綴來表示的,咱們把相應的修飾符添加在事件名稱後面就行了,如:
<!-- 阻止單擊事件繼續傳播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件再也不重載頁面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修飾符能夠串聯 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修飾符 --> <form v-on:submit.prevent></form> <!-- 添加事件監聽器時使用事件捕獲模式 --> <!-- 即元素自身觸發的事件先在此處理,而後才交由內部元素進行處理 --> <div v-on:click.capture="doThis">...</div> <!-- 只當在 event.target 是當前元素自身時觸發處理函數 --> <!-- 即事件不是從內部元素觸發的 --> <div v-on:click.self="doThat">...</div>
.stop
.prevent
.capture
.self
.once
.passive
注意:使用修飾符時,順序很重要;相應的代碼會以一樣的順序產生。所以,用v-on:click.prevent.self
會阻止 全部的點擊,而v-on:click.self.prevent
只會阻止對元素自身的點擊。注意這一點對咱們定位bug
時很關鍵。
咱們能夠用 v-model
指令來處理用戶輸入。 v-model
指令能夠在表單 <input>
、<textarea>
及 <select>
元素上建立雙向數據綁定,它會根據控件類型自動選取正確的方法來更新元素。v-model
本質上是語法糖,它負責監聽用戶的輸入事件以更新數據,並對一些極端場景進行一些特殊處理。
看看如何使用:
<template> <div> <input type='text' placeholder='Enter a todo..' v-model='todo'> <div>{{ todo }}</div> </div> </template> <script> export default { name: 'HelloWorld', data() { return { todo: '', }; }, }; </script>
這裏須要注意,在 <textarea>
中使用文本插值並不會生效,應用 v-model
來代替。
<template> <div> // ... <!-- <textarea placeholder='add multiple lines'>{{ todo }}</textarea> // 不生效 --> <textarea v-model='todo' placeholder='add multiple lines'></textarea> </div> </template>
<template> <div> <input type='radio' id='one' value='One' v-model='picked'> <label for='one'>One</label> <br> <input type='radio' id='two' value='Two' v-model='picked'> <label for='two'>Two</label> <br> <span>Picked: {{ picked }}</span> </div> </template> <script> export default { name: 'HelloWorld', data() { return { picked: '', }; }, }; </script>
綁定到布爾值:
<template> <div> <input type='checkbox' id='checkbox' v-model='checked'> <label for='checkbox'>{{ checked }}</label> </div> </template> <script> export default { name: 'HelloWorld', data() { return { checked: '', }; }, }; </script>
綁定到同一個數組:
<template> <div> <input type='checkbox' id='jack' value='Jack' v-model='checkedNames'> <label for='jack'>Jack</label> <input type='checkbox' id='john' value='John' v-model='checkedNames'> <label for='john'>John</label> <input type='checkbox' id='mike' value='Mike' v-model='checkedNames'> <label for='mike'>Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> </div> </template> <script> export default { name: 'HelloWorld', data() { return { checkedNames: [], }; }, }; </script>
<template> <div> <select v-model='selected'> <option disabled value>請選擇</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> </template> <script> export default { name: 'HelloWorld', data() { return { selected: '', }; }, }; </script>
<template> <div> <select v-model='selected' multiple style='width: 50px;'> <option>A</option> <option>B</option> <option>C</option> </select> <br> <span>Selected: {{ selected }}</span> </div> </template> <script> export default { name: 'HelloWorld', data() { return { selected: [], }; }, }; </script>
很是常見的一個場景是,用 v-for
渲染的動態選項:
<template> <div> <select v-model='selected'> <option v-for='option in options' v-bind:value='option.value' v-bind:key='option.value' >{{ option.text }}</option> </select> <span>Selected: {{ selected }}</span> </div> </template> <script> export default { name: 'HelloWorld', data() { return { selected: 'A', options: [ { text: 'One', value: 'A' }, { text: 'Two', value: 'B' }, { text: 'Three', value: 'C' }, ], }; }, }; </script>
在 HelloWorld
組件中,有一組 style
標籤:
<!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> // ... </style>
這就意味着咱們能夠在這個組件中定義任何樣式。默認 style
標籤上加了一個 scoped
屬性,表示樣式只在本組件內部生效,不用擔憂會影響其餘組件。
<style src="./style.css" scoped> // ... </style>
在 vue
中 class
綁定和 style
綁定都是用 v-bind
指令。 v-bind
指令容許咱們動態控制什麼時候以及是否應用 CSS
類和樣式,以及 CSS
屬性和值。看看怎麼使用:
<template> <div> <div v-bind:class='{ banner: showBanner}'></div> </div> </template> <script> export default { data() { return { showBanner: true, }; }, }; </script> <style scoped > .banner { background-color: purple; width: 100%; height: 30px; } </style>
打開瀏覽器,咱們會看到一個紫色的長方形。若是想在 showBanner
爲 false
的時候顯示長方形,只須要對 showBanner
取反便可:
<div v-bind:class='{ banner: !showBanner}'></div>
那若是須要綁定多個 class
,要怎麼辦呢?
<div v-bind:class="{ banner: showBanner, 'another-class': showClass }"></div>
用逗號分隔,而後在組件的 data
中定義另外一個布爾屬性,並在樣式中定義 .another-class
便可。
可是若是 calss
繼續增多,這種方式會讓 template
變得很不乾淨,咱們能夠這樣修改:
<template> <div> <div v-bind:class='classObject'></div> </div> </template> <script> export default { data() { return { classObject: { banner: true, bannerBorder: true, // More classes here if you want.. }, }; }, }; </script> <style scoped > .banner { background-color: purple; width: 100%; height: 30px; } .bannerBorder { border: 3px solid yellow; } </style>
class
綁定的數據對象沒必要內聯定義在模板裏,抽離出來放在 data
函數的返回值裏面。
和 class
綁定同樣,vue
也使用 v-bind
指令來綁定 style
:
<template> <div> <div v-bind:style='{ backgroundColor: bgColor, width: bgWidth, height: bgHeight }'></div> </div> </template> <script> export default { data() { return { bgColor: 'yellow', bgWidth: '100%', bgHeight: '30px', }; }, }; </script>
爲了讓模板更加乾淨,咱們也能夠像下面這樣調整:
<template> <div> <div v-bind:style='styleObject'></div> </div> </template> <script> export default { data() { return { styleObject: { backgroundColor: 'yellow', width: '100%', height: '30px', }, }; }, }; </script>
注意:css
屬性名能夠用駝峯式 (camelCase
) 或短橫線分隔 (kebab-case
) 來命名。使用短橫線分割時,須要用單引號把屬性名括起來。
學習完 Vue
的基礎語法,咱們能夠寫一個 Todolist
來檢驗一下本身:
代碼可參考:https://github.com/IDeepspace...
歡迎關注個人博客: https://togoblog.cn/