1. 程式人生 > 實用技巧 >【轉】 前端筆記之Vue(一)初識SPA和Vue&webpack配置和vue安裝&指令

【轉】 前端筆記之Vue(一)初識SPA和Vue&webpack配置和vue安裝&指令

【轉】 前端筆記之Vue(一)初識SPA和Vue&webpack配置和vue安裝&指令

一、單頁面應用(SPA

1.1 C/SB/S頁面架構的轉變

C/S:客戶端/伺服器(Client/Server)架構的軟體。

C/S 軟體的特點:

① 從window桌面雙擊開啟

② 更新的時候會替換原有的,原有的必須刪除,不能重新整理。

③ 在其他的裝置上使用的時候,也要安裝軟體。

B/S :瀏覽器和伺服器(Browser/Server)架構

B/S 軟體的特點:

不需要安裝任何的客戶端,是通過瀏覽器輸入網址開啟的。

更新的時候不需要重新安裝軟體,你只需要重新整理頁面,程式就能更新。

在其他裝置端,不需要安裝任何其他的軟體,瀏覽器足可以解決所有的問題。

Dashboard叫做儀表盤專案,通俗的講就是***管理平臺。比如進銷存管理平臺、汽車銷售管理平臺、寵物店管理平臺。

特點1:這種專案幾乎都是單頁面應用(Single Page Application)簡稱SPA

將原來PC桌面的應用程式,放到瀏覽器中實現。現在的用人需求很大,不管是政府機構、教育機構、外包機構、銷售機構都在開發自己的新專案,或者把老專案搬到網頁上。比如阿里雲的管理平臺,特別像桌面的app,現在是在瀏覽器中實現的。

所有頁面的URL網址,只有#後面的內容在變化,而#之前的內容沒有變化,整個專案就是一個html頁面。

網頁沒有發生跳轉,而是

DOM的整體上樹、下樹。這樣的好處是,讓本地變數可以在本地持久的時間變長。使用頁面內的錨點hash符號來標記的路由,也就是說點選任何連結,頁面實際上沒有任何跳轉,所有頁面的改變都是JS完成的,JS命令一些元件消失,命令新的一些元件上樹。所以稱為“單頁面應用”

頁面的URL沒有變化,變化的只是hash符號後面的部分:

特點2:都是元件化的

兩個不同的頁面中(實際上是一個頁面),都有日期選擇框,發現日期選擇框都是相同的,我們叫做“元件(components)”。

也就是說,這些日曆元件,不管是HTMLCSSJavaScript都能複用。

下圖中的每一個紅框都可以認為是元件:

特點3:所有的DOM元素都是動態上下樹的

檢視頁面原始碼,發現頁面上的所有DOM結構都不在原始碼中,也就是說DOM結構是JavaScript程式控制上樹的,所有的部件,都是元件、元件巢狀元件、集體被JavaScript上樹。

總結,一個好的單頁面應用的框架,必須要能提供:

l優秀的路由機制,能捕獲使用者URLhash部分,決定什麼元件顯示和隱藏;

lJavaScript控制組件動態上樹、下樹的能力;

l元件的建立、複用、巢狀能力;

l元件的資料傳遞的能力。


1.2三大框架的出現

AngularReactVue都是做什麼的?

它們都是JS架構,都是用來做單頁面應用設計的。

Angular

AngularJS誕生於2009年,由Misko Hevery 等人建立,後為Google所收購。是一款優秀的前端JS框架,已經被用於Google的多款產品當中。Angular是第一個實現“資料變化,檢視自動變化”的框架,並且首創了元件化開發模式。Angular有著諸多特性,最為核心的是:MVC、模組化、自動化雙向資料繫結、語義化標籤、依賴注入、服務、控制器等等。

Angular的出現,有了前端的元件化。

前端的元件化開發:它是一種易於插拔,模組化的開發形式。HTMLCSSJS邏輯都封裝到一個元件中,在其他的頁面可以輕鬆地顯示。

AngularAMD模式,專案需要使用require.js配合,和時代的CMD主流背道而馳,2015年開始落寞了。Angular2016年出了22017年出了45,都是CMD模式的,但是使用者已經不買賬了。

React

React 起源於 Facebook 的內部專案,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意。就決定自己寫一套,用來架設Instagram 的網站。做出來以後,發現這套東西很好用,就在20135月開源了。

React主要用於構建UI。你可以在React裡傳遞多種型別的引數,如宣告程式碼,幫助你渲染出UI、也可以是靜態的HTML DOM元素、也可以傳遞動態變數、甚至是可互動的應用元件。

React非常輕,只提供了少量了API,和相關的元件。

React可以ReduxFlux等框架配合使用。

React 使用 Virtual DOM技術,使他渲染更快速,記憶體開銷小。

ReactCMD模式的,並且創造性的和webpack進行合作,將所有的js程式碼實時構建為一個js檔案,程式設計的時候非常的清爽,非常利於團隊合作,所以大量的使用者就開始使用React開發自己的專案。

Vue

Vue是中國人尤雨溪發明的,它的資料驅動檢視的實現是最優雅的。它是一個集大成者,集成了AngularReact的優點,摒棄了它們的缺點。是一個構建資料驅動的 web 介面的漸進式框架。Vue.js 的目標是通過儘可能簡單的 API 實現響應的資料繫結和組合的檢視元件。它不僅易於上手,還便於與第三方庫或既有專案整合。

Vue的作者,發現了JS的一個神奇之處,Object.defineProperty的作用,可以用於檢視的更新。

AngularJS實現的機理是髒檢查。

React是setState()。


二、Vue介紹

2.1官網和作者

官網:https://cn.vuejs.org/

Vue是一門mvvm的框架,繼承了Angular的雙向資料繫結和指令的優點,繼承了React的快速製作元件的能力,同時也擁有非常類似與Redux的單向資料流動的思想,最主要Vueapi都是中文的,非常好學。

2.2 Vue是一門mvvm框架

MVVM框架:一切的檢視都是和資料相關聯的。資料變化了,檢視就自動變化。而不需要控制器去命令模組做什麼然後渲染什麼檢視

ReactVueAngular都是簡化了模組化開發,這些MVVM框架到底簡化了什麼

1)元件方便建立了(建立一個元件只需要寫一個類或者一個函式)

2)元件的可插拔性高

3)元件的資料傳輸簡單了

4)路由,單頁面應用的hash路由

5)只關心資料,不關心DOM

資料叫做model(模型),因為對資料的所有操作都是模型的任務;檢視叫做view。在MVVM中出現了view-model這個層,它可以“監聽”model 的任何改變,讓檢視自動變化。從而我們不需要關心DOM操作,只需要關心資料的變化即可。

ReactVueAngular中都提供了view-model層。

比如,資料:

[
    {"id":1,"name":"小明","age":12},
    {"id":2,"name":"小紅","age":12},
    {"id":3,"name":"小強","age":12},
]

它有對應的DOM結構:

<table>
    <tr>
        <td>1</td>
        <td>小明</td>
        <td>12</td>
    </tr>
    <tr>
        <td>2</td>
        <td>小紅</td>
        <td>12</td>
    </tr>
    <tr>
        <td>3</td>
        <td>小強</td>
        <td>12</td>
    </tr>
</table>
結構

第一次根據資料建立DOM是非常簡單的,但是如果資料發生變化,我們必須要手動調整DOM的變化。

非常的不方便,尤其是系統很大的時候,不方便。

此時MVVM模式,就能簡化這些操作:資料一變化,DOM自動變化。

除了MVCMVVM模式,還有MVP。統稱MV*模式。

ReactVueAngular中都提供:

1)路由能力、元件的管理能力、元件的巢狀能力、元件的資料傳遞能力;

2)資料變化檢視自動變化。


2.3 Vue的虛擬DOM

Virtual DOM是什麼呢?

Vue.js(2.0版本)React的其中最大一個相似之處,就是他們都使用了一種叫’Virtual DOM’的東西。所謂的Virtual DOM基本上說就是它名字的意思:虛擬DOMDOM樹的虛擬表現。它的誕生是基於這麼一個概念:改變真實的DOM狀態遠比改變一個JavaScript物件的花銷要大得多。

Virtual DOM是一個對映真實DOMJavaScript物件,如果需要改變任何元素的狀態,那麼是先在Virtual DOM上進行改變,而不是直接改變真實的DOM。當有變化產生時,一個新的Virtual DOM物件會被建立並計算新舊Virtual DOM之間的差別。之後這些差別會應用在真實的DOM上。


2.4src引包體驗Vue魅力

src引入vue.js(現在不是webpack進行CMD規範的構建)來快速認知。

https://vuejs.org/js/vue.js

通過vuejs的包學習基礎語法,然後再用webpack

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h1>{{a}}</h1>
    </div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
     //Vue所有的元件都是內部建立的,這裡是唯一一次new Vue()
     //不管專案有多大,元件有多少個,一定只有一個new Vue()。
     //這是一個例項
     new Vue({
        el:"#app", //掛載點
        data:{
            a : 100
        }
     })
</script>
</html>

首先認知一個事情:VueReact的區別,Vue在寫例項,React在寫類。

MVVM框架:一切的檢視都是和資料相關聯,資料變化,檢視就自動變化。


2.5 Vue檢視更新原理

<body>
    <div id="app">
        <h1>{{a}}</h1>
        <button v-on:click="add"></button>
        <button v-on:click="minus"></button>
    </div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
     //Vue所有的元件都是內部建立的,這裡是唯一一次new Vue()
     //不管專案有多大,元件有多少個,一定只有一個new Vue()。
     //這是一個例項
     new Vue({
        el:"#app", //掛載點
        data:{
            a : 100
        },
        methods:{
            add(){
                this.a++
            },
            minus(){
                this.a--
            }
        }
     })
</script>

現在資料變化了,檢視就自動變化,這是MVVM框架的最大特點。

因為Vue做資料和檢視相關變化,原理是“資料劫持”。Object.defineProperties()。定義Vue中元件物件data中的所有變數的setter,讓他們在被設定的時候,重新整理相關檢視。

<body>
    <button>按我</button>
</body>
<script type="text/javascript">
     var obj = { //只要這個物件被賦值,立馬觸發set函式
        a : 100
     }

     Object.defineProperties(obj, {
        a : {
            set:function(){
                alert("你在修改a"); //監聽這個屬性被重新賦值
            },
            get:function(){
                alert("你在讀取a");
            }
        }
     })

     document.getElementsByTagName("button")[0].onclick = function(){
        obj.a++; //obj.a的值變化Object.defineProperties()函式的set和get就能攔截到
     }
</script>
示例程式碼

三、配置webpack和安裝vue

3.1配置webpack

Vue 提供了一個官方的 CLI,可以瞬間建立一個專案,但是初學者別用cli起步,先自己手動配置。

webpack中文網:https://doc.webpack-china.org/configuration/

VueReact都是CMD架構(importexport),但目前所有瀏覽器都不支援CMD規範

所以現在VueReact的專案都用webpack打包。用webpack打包只是暫時的,也許在幾年內前端就不用webpack了。

第一步:先建立專案資料夾,配置webpackCMD規範,建立package.json檔案

安裝webpack
npm install -g [email protected]

webpack4.0以上版本都要安裝webpack-cli依賴
npm install -g webpack-cli

安裝 webpack-dev-server,這是一個前端的模擬小伺服器,寫不了介面,但是能靜態化資料夾。
npm install -g webpack-dev-server

配置webpack.config.js檔案(複製官網的配置)

webpack 4.0以上版本必須增加mode屬性,它有兩個值:

lproduction (上線版)

ldevelopment (開發版)

開發時,設定mode屬性為development,要不然就混淆加密打包很慢。

const path = require('path');

module.exports = {
     //程式的入口檔案
     entry: "./www/app/app.js",

     //程式的出口(打包的檔案)
     output : {
        //打包檔案輸出的路徑
        path : path.resolve(__dirname, "www/dist"),
        //打包檔案的名稱
        filename : "all.js",
        publicPath:"/public/" //這是對webpack-dev-server的配置,配置虛擬路徑
     },
     //讓webpack監聽變化,自動打包
     watch : true,
     mode : "development",
     //配置webpack的模組外掛
     module:{
        //關於模組的配置規則
        rules : [{
            //模組規則(配置 loader、解析器等選項)
            test : /\.js$/,  //解析的時候匹配到的都是js檔案
            include: [
              path.resolve(__dirname, "www/app")    //翻譯什麼資料夾
            ],
            exclude: [
              path.resolve(__dirname, "node_modules") //不翻譯什麼資料夾
            ],
            // loader : "babel-loader",
            // options : {
            //     presets : ["es2015","es2016"]
            // }
        }]
     }
}

publicPathwebpack-dev-server在記憶體中生成的臨時資料夾(專案中物理磁碟上沒有這個資料夾),並且把/public/all.js檔案路由到了打包的檔案,是為了編譯速度更快,還能保護硬碟,同時webpack-dev-server提供了前端伺服器,埠自定義。

然後啟動專案:

webpack-dev-server --content-base ./www --port 8080

--content-base表示以www資料夾作為一個靜態化根目錄

--port 表示埠號

以上啟動命令很繁瑣,我們可以在package.json中,配置一個快速啟動命令:

{
  "name": "vue_study",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev" : "webpack-dev-server --content-base ./www --port 8080"
  },
  "author": "",
  "license": "ISC"
}

以後專案直接可以用以下命令啟動:

npm run dev

以後專案開啟http://127.0.0.1:8080,不要直接雙擊index.html頁面了。

webpack-dev-server在做了兩件事:

1)在打包js檔案

2)靜態化www資料夾,說白了就是幫我寫了一個app.use(express.static('www'))

index.html檔案,要改變scriptsrc引用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>
<body>

</body>
<script type="text/javascript" src="public/all.js"></script>
</html>


3.2安裝配置Vue

接下來,配置Vue,只需要5個依賴就能起步:

vuevue-loader(安裝Vue時會提醒你安裝css-loadervue-template-compiler

npm install --save vue

安裝其它4個開發依賴:

npm install --save-dev vue-loader
npm install --save-dev css-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler

注意:什麼是loader

webpack在打包的時候,順便做的事情,就是loader

5個依賴的作用:

vue 核心(語法)

css-loader webpack能識別樣式表,打包樣式表到index頁面中

vue-style-loader 識別內嵌樣式表

vue-loader 識別.vue元件檔案的

vue-template-compiler 識別<template></template>

babel-loader是翻譯ES6語法的,無需安裝,因為vue-loader中含有babel-loader

補充webpackvue配置:

配置webpack.config.js,這裡手冊很坑,是兩個地方告訴你怎麼配置resolvemodule兩個屬性。

resolve屬性:https://cn.vuejs.org/v2/guide/installation.html

module屬性:https://vue-loader-v14.vuejs.org/zh-cn/options.html#loaders

var path = require('path');
const {VueLoaderPlugin} =  require("vue-loader"); //最新版webpack需要引入此外掛

module.exports = {
    //程式的入口檔案
    entry: './www/app/main.js',
    //程式的出口檔案(被打包的檔案)
    output: {
        //打包檔案輸出的路徑
        path: path.resolve(__dirname, './www/dist'),
        //打包檔案的名稱
        filename: 'all.js',
        //這是對webpack-dev-server的配置,是一個虛擬路徑
        // publicPath:"public" //這是對webpack-dev-server的配置,配置虛擬路徑
    },
    //自動監聽
    watch:true,
    mode : "development",
    //配置webpack的模組外掛
    module:{
        // 關於模組配置
        rules: [
            // 模組規則(配置 loader、解析器等選項)
            {
                test: /\.js?$/,  //解析的時候匹配到的都是js檔案
                include: [path.resolve(__dirname, "www/app")], //翻譯什麼資料夾中的檔案
                exclude: [path.resolve(__dirname, "node_modules")], //不翻譯什麼資料夾
                // loader: "babel-loader",
                // //翻譯字典
                // options: {
                //   presets: ["es2015","es2016"]
                // }
            },
            {
                test: /\.vue?$/,  //解析的時候匹配到的都是js檔案
                include: [path.resolve(__dirname, "www/app")], //翻譯什麼資料夾中的檔案
                exclude: [path.resolve(__dirname, "node_modules")], //不翻譯什麼資料夾
                loader: "vue-loader"
            },
            {
                test: /\.css?$/,  //解析的時候匹配到的都是js檔案
                include: [path.resolve(__dirname, "www/app")], //翻譯什麼資料夾中的檔案
                exclude: [path.resolve(__dirname, "node_modules")], //不翻譯什麼資料夾
                use: ["vue-style-loader","css-loader"]
            }
        ]
    },
    resolve: {
        alias: { //配置別名
          'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 時需用 'vue/dist/vue.common.js'
        }
    },
    //最新版webpack需要引入此外掛
    plugins:[
        new VueLoaderPlugin()
    ]
};

藍色部分是配置loader必須的語法,所有以.vue結尾的檔案都是vue-loader處理

紅色是vue必須的配置

main.js檔案寫vuehello world

import Vue from "vue";

new Vue({
    el:"#app",
    data:{
        a:100
    }
});
示例程式碼

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h1>{{a}}</h1>
    </div>
</body>
<script type="text/javascript" src="dist/all.js"></script>
</html>
示例程式碼

重啟webpack能看看見100,說明配置成功了。


四、Vue指令

下面正式學習vue,先從指令開始學起。官網指令API地址:https://cn.vuejs.org/v2/api/

Vue中所有的指令都是v-開頭的。

指令系統的原理就是正則表示式,所有的指令的值都是引號包裹(引號是正則表示式工作的定界符),正則表示式會進行提取,然後執行。所以不要認為引號中的值是字串,裡面的內容是“活”的。

4.1模板插值

4.1.1 v-text模板插值

{{}}v-text指令是完全等價的。

index.html

<div id="app">
    <h1 v-text="a"></h1>
    <h1>{{a}}</h1>
    <h1>{{100 * 100}}</h1>
    <h1>{{parseInt(Math.random() * 100)}}</h1>
    <h1>{{arr.reduce((a,b)=> a+b)}}</h1>
    <h1>{{ 3 > 8 ? 5 : 10000 }}</h1>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        a : 100,
        arr : [100,200,300]
    }
})

重點注意:

{{}}中只能寫表示式,不能寫語句。

什麼是表示式,呼叫函式時,可以稱為實參的東西,就是表示式。

{{}}中能夠寫:

簡單運算

函式的呼叫

三元運算子

filtermapreduce等函式

Math物件、Date物件、Number()建構函式

不能寫:

for()語句

if語句


4.1.2 v-html

v-text不能識別DOM元素,只能用v-html

index.html

<div id="app">
    <h1 v-html="a"></h1>
    <h1 v-html="b"></h1>
</div>

main.js

import Vue from 'vue';

new Vue({
    el : "#app",
    data : {
        a : '<h1 style="color:red;">哈哈</h1>',
        b : '<input type="text" />'
    }
})

data中的資料,進行html轉換,樣式寫在行內。


4.2 v-on事件指令

4.2.1滑鼠事件

表示新增事件監聽,v-on叫指令 :click叫引數。“v-on:”可以簡寫為“@

<div id="app">
    <h1>{{a}}</h1>
    <button @click='add'>按我+</button>
    <button v-on:click='add'>按我+</button>
    <button v-on:mouseenter='add'>觸控+</button>
    <button v-on:dblclick='jian'>雙擊-</button>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        a : 100
    },
    methods : {
        add(){
            this.a++
        },
        jian(){
            this.a--
        }
    }
})
<button v-on:click.once='add'>只觸發一次+</button>


4.2.2鍵盤事件

index.html

<div id="app">
    <input type="text" v-on:keydown.13='tijiao($event)'>
    <input type="text" v-on:keyup.enter='haha'>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {

    },
    methods : {
        tijiao(e){
            console.log(e.target.value)
        },
        haha(){
            alert("回車鍵鬆開了")
        }
    }
})

當按下回車鍵的時候,觸發methods的方法,監聽鍵盤按鍵時,修飾符是13(表示回車鍵)

如果需要用event事件物件,傳入$event即可。

內建按鍵修飾符有很多

https://cn.vuejs.org/v2/guide/events.html


4.3 v-bind動態指令

v-bind可以將值變成“動態”的

v-bind:什麼屬性都可以,並且“v-bind:”可以簡寫成“:

比如:

v-bind:value
v-bind:style
v-bind:class
v-bind:name
v-bind:alt
v-bind:disable
v-bind:title
v-bind:src

4.3.1 v-bind:class物件語法

index.html

<head>
    <style type="text/css">
        .cur{color:red;}
        .bgcur{background:pink;}
    </style>
</head>
<body>
<div id="app">
    <h1 v-bind:class="{cur:true, bgcur:true}">哈哈</h1>
        <h1 v-bind:class="{cur:isClass, bgcur:isBgClass}">哈哈</h1>
        <button @click="changeClass">按我切換</button>
    </div>
</body>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        isClass:true,
        isBgClass:true
    },
    methods : {
        changeClass(){
            this.isClass = !this.isClass;
            this.isBgClass = !this.isBgClass;
        }
    }
})


4.3.2 v-bind:class陣列語法

index.html

<div id="app">
<h1 v-bind:class="['cur', 'bgcur']">哈哈</h1>
    <h1 v-bind:class="[isClass,isBgClass]">哈哈</h1>
    <button @click="changeClass">按我切換</button>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        isClass:'cur',  //類名
        isBgClass:'bgcur'  //類名
    },
    methods : {
        changeClass(){
            this.isClass = !this.isClass;
            this.isBgClass = !this.isBgClass;
        }
    }
})

4.3.3 v-bind:style物件語法

注意:這些值需要用引號包裹,否則會認為它是一個函式:

index.html

<div id="app">
    <h1 v-bind:style="{background:'red'}">哈哈</h1>
    <h1 :style="{background:'red'}">哈哈</h1>
    <h1 :style="{background:`rgb(${r}, ${g}, ${b})`}">哈哈</h1>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
         r : 100,
         g : 200,
         b : 255
    }
})


4.3.4 v-bind:style陣列語法

index.html

<div id="app">
<h1 :style="[{'background':'red', 'fontSize':'50px'}]">哈哈</h1>
    <h1 :style="[obj]">哈哈</h1>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        obj : {
            'background':'red',
            'fontSize':'50px'
        }
    }
})

4.3.5 v-bind:其他屬性

index.html

<div id="app">
    <img :src="url" >
    <a :href="link">百度</a>
    <button :disabled="b">按鈕</button>
    <input type="text" :value="a">
    <input type="text" :placeholder="a">
    <div :style="yangshi"></div>
    <h1 :class="leiming">文字</h1>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        a : 100,
        b : "disabled",
        url : "images/baby1.jpg",
        link: "http://www.iqianduan.cn",
        yangshi : {
            "background": 'orange',
            "width":'100px',
            "height":'100px',
        },
        leiming : {
            "da" : true,
            "xie" : false,
            "hong" : true
        }
    }
})

4.4 v-ifv-else上下樹

v-if是控制DOM上下樹的,v-iftrue則上樹,false則下樹。

v-else必須緊跟著v-if,中間不能有任何間隔,否則報錯,如果有間隔可以使用兩個v-if讓他們互反。

index.html

<div id="app">
    <h1 v-if="isShow">如果</h1>
    <h2 v-else="isShow">否則</h2>
    <button @click="showClick">按我</button>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
       isShow:true
    },
    methods : {
        showClick(){
            this.isShow = !this.isShow;
        }
    }
})

v-ifv-else有間隔就報錯:

解決方法:用兩個if

<h1 v-if="isShow">如果</h1>
<h2 v-if="!isShow">否則</h2>
<button @click="showClick">按我</button>

4.5 v-show顯示/隱藏

v-show是控制DOM的隱藏和顯示,原理是CSSdisplay:noneblock

index.html

<div id="app">
    <h1 v-show="isShow">哈哈</h1>
    <h1 v-show="!isShow">嘿嘿</h1>
    <button @click="showClick">{{isShow ? "按我消失" : "按我顯示"}}</button>
</div>

main.js

import Vue from 'vue';
new Vue({
    el: "#app",
    data: {
        isShow : true
    },
    methods:{
        showClick(){
            this.isShow = !this.isShow
        }
    }
})

一般來說,v-if有更高的切換開銷,而v-show有更高的初始渲染開銷。

因此,如果需要非常頻繁的切換,使用v-show較好,如果在執行時條件很少改變,則使用v-if較好。


4.6 v-for迴圈指令

用來迴圈某一個元素,資料必須是陣列或類陣列物件,使用ofin關鍵字。

4.6.1迴圈陣列

index.html

<div id="app">
    <ul>
        <li v-for="item in arr" :key="item">{{item}}</li>
    </ul>
    <ul>
        <li v-for="(item,index) in arr" :key="item">{{item}} {{index}}</li>
    </ul>
    <table>
       <tr v-for="(item,index) in students" :key="item.id">
           <td>{{item.id}}</td>
           <td>{{item.name}}</td>
           <td>{{item.age}}</td>
       </tr>
    </table>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        arr : ["蘋果","鴨梨","桃子","西瓜"],
        students : [
            {"id":1001, "name":"小明", "age" :12},
            {"id":1002, "name":"小紅", "age" :13},
            {"id":1003, "name":"小剛", "age" :14}
        ]
    }
})
示例程式碼

index的下標是從0開始


4.6.2迴圈物件

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
         obj : {"name":"小明","sex":"男","age":12}
    }
})

index.html

<div id="app">
     <ul>
         <li v-for="(item,key,index) in obj" :key="index">
             {{index}}
             {{key}}
             {{item}}
         </li>
     </ul>
</div>


4.6.3迴圈常數

index.html

<div id="app">
     <ul>
         <li v-for="(item,index) in 10">
            {{item}} {{index}}
         </li>
     </ul>
</div>

迴圈常數,item是從1開始迭代,index是從0開始。

https://cn.vuejs.org/v2/guide/list.html#key


九九乘法表:

<div id="app">
     <table border="1">
        <tr v-for="i in 9">
            <td v-for="j in 9" v-show="i >= j">
                {{i}} * {{j}} = {{i * j}}
            </td>
        </tr>
     </table>
</div>

這些陣列方法會重新出發v-for檢視更新渲染:

index.html

<div id="app">
     <input type="text" @keyup.enter="tijiao" v-model="txt">
     <ul>
         <li v-for="item in arr">{{item.title}}</li>
     </ul>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
        arr : [],
        txt : ''
    },
    methods :{
        tijiao(){
            this.arr.push({"title" : this.txt}) //把輸入的內容插入到陣列,會重新渲染檢視
            this.txt = ''
        }
    }
})


4.7 v-model雙向資料繫結

雙向資料繫結借鑑了Angular。所有表單元素(單選、文字框、複選)等都能用v-model雙向和data繫結!

v-model幫表單元素在內部做了兩個事情:

1)添加了監聽

2)添加了value

l受控就是雙向繫結:控制元件從data要值,控制元件要變化,就改變data的值

React中做表單控制元件的受控,要寫value={}onChange={};

但是在vue中,只需使用v-model將實現快速的資料雙向繫結。

https://cn.vuejs.org/v2/guide/forms.html


4.7.1 input的雙向資料繫結

index.html

<body>
    <div id="app">
        <h3>{{a}}</h3>
        <input type="text" v-model="a">

        <p>
            <input type="radio" name="sex" v-model="b" value="男"><input type="radio" name="sex" v-model="b" value="女"></p>
        <p>你的性別是:{{b}}</p>

        <p>
            <input type="checkbox" v-model="c" value="看書">看書
            <input type="checkbox" v-model="c" value="打球">打球
            <input type="checkbox" v-model="c" value="吃飯">吃飯
        </p>
        <p>你的愛好是:{{c}}</p>

        <p><input type="range" max="100" v-model="d"></p>
        <p>你的音量是:{{d}}</p>
    </div>
</body>
示例程式碼

main.js

import Vue from "vue";

new Vue({
    el:"#app",
    data:{
         a:"請輸入內容",
         b:"男",
         c:["打球","看書"],
         d:30
    }
})
例項程式碼


4.7.2 input-number

index.html

<div id="app">
    <h1>{{num}}</h1>
    <h1>{{typeof num}}</h1>
    <input type="number" v-model.number="num">
    <h1>{{txt}}</h1>
    <input type="text" v-model.trim='txt'>
</div>

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
         num : 0,
         txt : ''
    }
})

預設型別:

輸入內容修改後型別:

v-model新增修飾符限制類型:

<input type="number" v-model.number="num">

input新增.trim修飾符,能過濾首位的空格,中間的不行。

<input type="text" v-model.trim="num">

change”時而非“input”時觸發:

<input v-model.lazy="txt" >

4.7.3 textarea

微博釋出框:文字輸入框如果超出140字時,動態新增一些類和屬性,字型變紅,按鈕不可點選。

index.html

<style type="text/css">
    .danger{color:red;}
</style>
<div id="app">
    <textarea cols="30" rows="10" v-model='txt'></textarea>
    <span :class="{danger: txt.length > 140}">當前共{{txt.length}}字/140字</span>
<button :disabled="txt.length == 0 || txt.length > 140">釋出</button>
<button :disabled="txt.length == 0" @click="clear">清空</button>
</div>

main.js

import Vue from 'vue';
new Vue({
    el: "#app",
    data: {
        txt:""
},
methods : {
    clear(){
        this.txt= ""
    }
}
})

4.7.4雙向資料繫結-受控的列

index.html

<div id="app">
    <div>
        <label><input type="checkbox" value="id" v-model="showCols">學號</label>
        <label><input type="checkbox" value="name" v-model="showCols">姓名</label>
        <label><input type="checkbox" value="sex" v-model="showCols">性別</label>
        <label><input type="checkbox" value="age" v-model="showCols">年齡</label>
    </div>
    <table>
       <tr>
           <th v-show="showCols.includes('id')">學號</th>
           <th v-show="showCols.includes('name')">姓名</th>
           <th v-show="showCols.includes('sex')">性別</th>
           <th v-show="showCols.includes('age')">年齡</th>
       </tr>
       <tr v-for="item in arr">
           <td v-show="showCols.includes('id')">{{item.id}}</td>
           <td v-show="showCols.includes('name')">{{item.name}}</td>
           <td v-show="showCols.includes('sex')">{{item.sex}}</td>
           <td v-show="showCols.includes('age')">{{item.age}}</td>
       </tr>
    </table>
</div>
示例程式碼

main.js

import Vue from 'vue';
new Vue({
    el : "#app",
    data : {
         showCols : ['id', 'name', 'sex', 'age'],
         arr : [
            {"id":1001, "name":"小明","sex":"男","age":12},
            {"id":1002, "name":"小紅","sex":"女","age":13},
            {"id":1003, "name":"小花","sex":"女","age":14},
            {"id":1004, "name":"小剛","sex":"男","age":15},
            {"id":1005, "name":"小黑","sex":"男","age":16}
         ]
    }
})
示例程式碼