Vue 基礎語法

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

1、建立組件

vue 中,有好幾種方式用來建立組件,後面會單獨寫一篇文章來介紹。

HelloWord.vue 文件中的內容分爲三個部分:前端

<template>
  ...
</template>

<script>
  ...
</script>

<style>
 ...
</style>

分別在這三類標籤裏面寫入結構、腳本、樣式。 這個文件以 .vue 結尾(注意:其餘建立組件方式是以 .js 結尾),這是 vue 中建立組件的一種方式:單文件組件。換句話說就是每一個 .vue 文件就是一個組件。vue

有一點須要注意:template 只能容許一個子元素。java

2、導入組件

如今的文件中,是在路由 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 組件中的內容:VueLogoHelloWorld 組件裏的內容。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 對象中定義多個屬性,指向引入的組件便可。

3、插值和指令

一、插值(Interpolation)

文本插值:

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)

指令 (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-ifv-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,這裏再也不一一講述。

4、事件處理

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 時很關鍵。

5、處理用戶輸入

咱們能夠用 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>

6、樣式

HelloWorld 組件中,有一組 style 標籤:

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
// ...
</style>

這就意味着咱們能夠在這個組件中定義任何樣式。默認 style 標籤上加了一個 scoped 屬性,表示樣式只在本組件內部生效,不用擔憂會影響其餘組件。

一、連接到外部樣式表

<style src="./style.css" scoped>
// ...
</style>

二、class 綁定

vueclass 綁定和 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>

打開瀏覽器,咱們會看到一個紫色的長方形。若是想在 showBannerfalse 的時候顯示長方形,只須要對 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 函數的返回值裏面。

三、style 綁定

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) 來命名。使用短橫線分割時,須要用單引號把屬性名括起來。

7、 Todolist

學習完 Vue 的基礎語法,咱們能夠寫一個 Todolist 來檢驗一下本身:

代碼可參考:https://github.com/IDeepspace...

歡迎關注個人博客: https://togoblog.cn/
相關文章
相關標籤/搜索