Vue全傢桶入門基礎教程

1. Vue概述

Vue(讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式JavaScript框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。

漸進式: 聲明式渲染→組件系統→客戶端路由→集中式狀態管理→項目構建

可以使用其中的一個或者多個

優點:

  • 易用:熟悉HTML,CSS.JavaScript知識後,可快速上手Vue
  • 靈活:在一個庫和一套完整框架之間自如伸縮
  • 高效:20kB運行大小,超快虛擬DOM

 2. Vue的基本使用

2.1 傳統開發模式對比

//原生JS
 <div id="msg"></div>
  <script type="text/javascript">
    var msg = 'Hello World'
    var div = document.querySelector('#msg');
    div.innerHTML = msg
  </script>
//jQuery
<div id="msg"></div>
  <script type="text/javascript" src="js/jquery.js"></script>
  <script type="text/javascript">
    var msg = 'Hello World';
    $('#msg').html(msg);
  </script>

2.2 Vue.js之HelloWorld基本步驟

引入Vue的方法:

1.下載Vue.js,然後在<script type='text/javascript' src='js/vue.js'></script>引入

2.使用CDN方法。 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

Vue的基本使用步驟:

​ 1、需要提供標簽用於填充數據

​ 2、引入Vue.js庫文件

​ 3、可以使用vue的語法做功能瞭

​ 4、把vue提供的數據填充到標簽裡面

//1.HelloWorld.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
</head>

<body>
  <div id="app">
      //插值表達式
    <div>{{num}}</div> 
    <div><button @click='handle'>點擊</button></div>
  </div>
 //引入vue
  <script type='text/javascript' src='js/vue.js'></script>
  <script type='text/javascript'>
    var vm = new Vue({
      el: '#app',
      data: {
        num: 0
      },
      methods: {
        handle: function () {
          this.num++;
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

2.3 Vue.js之HelloWorld細節分析

1. 實例參數分析

  • el:元素的掛載位置(值可以是CSS選擇器或者DOM元素)關聯起來
  • data:模型數據(值是一個對象)
  • methods,該屬性用於在Vue對象中定義方法。

2.插值表達式用法

  • 將數據填充到HTML標簽中
  • 插值表達式支持基本的計算操作

3. Vue代碼運行原理分析

概述編譯過程的概念(Vue語法經過Vue框架編譯成原生JS語法,才能夠被瀏覽器執行)

在這裡插入圖片描述

3. Vue 模板語法

3.1 模板語法概述

前端渲染:把數據填充到HTML標簽中

在這裡插入圖片描述

前端渲染方式:

  • 原生js拼接字符串
  • 使用前端模板引擎
  • 使用vue特有的模板語法(推薦)

原生js拼接字符串基本上就是將數據以字符串的方式拼接到HTML標簽中。

缺點:不同開發人員的代碼風格差別很大,隨著業務的復雜,後期的維護變得逐漸困難起來。

使用前端模板引擎是基於模板引擎art-template的一段代碼,與拼接字符串相比,代碼明顯規范瞭很多,它擁有自己的一套模板語法規則。

優點:大傢都遵循同樣的規則寫代碼,代碼可讀性明顯提高瞭,方便後期的維護。

缺點:沒有專門提供事件機制。

插值表達式 {{變量}}

  • 使用’mustache’語法 {{ msg }}(雙花括號)
  • mustache 標簽將會被替換為 data 對象上對應的 msg 屬性的值。
  • 隻要綁定的數據對象上的 msg 屬性發生改變,插值內容也會隨之更新。
<div id="app">
      <!-- this 指向 vm -->
      <p> {{ msg }} </p>
   </div>
   
   <script>
	var vm = new Vue({
    	el: ‘#app',
  		data: {
  			msg: 'hello vue.js'
  		}
  	})
	</script>

模板語法概述

  • 插值表達式
  • 指令
  • 事件綁定
  • 屬性綁定
  • 樣式綁定
  • 分支循環結構

3.2 指令

1.什麼是指令?

  • 自定義屬性:如在html5中定義,屬性均可隨意命名。
  • 指令的本質就是自定義屬性
  • 指令的格式:以v-開始(比如:v-cloak)

2.v-cloak指令用法

插值表達式存在的問題:“閃動”

如何解決該問題:使用v-cloak指令

v-cloak指令的用法
  1、提供樣式
   屬性選擇器
    [v-cloak]{
      display: none;
    }
  2、在插值表達式所在的標簽中添加v-cloak指令

背後的原理:先通過樣式隱藏內容,然後在內存中進行值的替換,替換好之後再顯示最終的結果

//02-指令v-cloak的用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
  [v-cloak]{
    display: none;
  }
  </style>
</head>
<body>
  <div id="app">
    <div v-cloak>{{msg}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var app = new Vue({
      el: '#app',
      data: {
        msg: 'Hello Vue'
      }
    });
  </script>
</body>
</html>

3 .數據綁定指令

  • v-text填充純文本

用於將數據填充到標簽中,作用於插值表達式類似,但是沒有閃動問題

  • v-html填充HTML片段

用於將HTML片段填充到標簽中,但是可能有安全問題

  • v-pre填充原始信息

顯示原始信息,跳過編譯過程(分析編譯過程)

//03-數據填充相關3個指令用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    <div v-text='msg'></div>
    <div v-html='msg1'></div>
    <div v-pre>{{msg}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Hello Vue',
        msg1: '<h1>HTML</h1>'
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

4.數據響應式

  • 如何理解響應式

html5中的響應式(屏幕尺寸的變化導致樣式的變化)
數據的響應式(數據的變化導致頁面內容的變化)

  • 數據綁定:將數據填充到標簽中,默認是響應式的
  • v-once隻編譯一次,顯示內容之後不再具有響應式功能

v-once的應用場景:如果顯示的信息後續不需要再修改,可以使用v-once提高性能。

//04-指令v-once的用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 v-once>{{message}}</h2>
  </div>
  <script>
    const app = new Vue({
      el: "#app",
      data: {
        message: "你好啊"
      }
    })
  </script>
</body>

</html>

在這裡插入圖片描述

3.3 雙向數據綁定

1.什麼是雙向數據綁定?

在這裡插入圖片描述

2.雙向數據綁定分析

Vue中使用v-model指令來實現標簽內容的綁定(雙向綁定).如表單元素和數據的雙向綁定

v-model隻能用於表單類型,就是輸入性控件,其他控件不能用,用v-bind

<input type='text' v-model='uname'/>
//05.雙向數據綁定.html
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <div>{{msg}}</div>
      <div>
        <input type="text" v-model='msg'>
      </div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /* 雙向數據綁定
        1、從頁面(用戶)到數據
        2、從數據到頁面  */
      var vm = new Vue({
        el: '#app',
        data: {
          msg: 'Hello Vue'
        }
      });
    </script>
  </body>
  </html>

在這裡插入圖片描述

案例解析:

當我們在輸入框輸入內容時,因為input中的v-model綁定瞭msg,所以會實時將輸入的內容傳遞給msg,msg發生改變。

當msg發生改變時,因為上面我們使用Mustache語法,將msg的值插入到DOM中,所以DOM會發生響應的改變。

3.MVVM設計思想

在這裡插入圖片描述

MVVM是Model-View-ViewModel的簡寫。它本質上就是MVC 的改進版。MVVM 就是將其中的View 的狀態和行為抽象化,讓我們將視圖 UI 和業務邏輯分開

  • View層:視圖層

在我們前端開發中,通常就是DOM層。主要的作用是給用戶展示各種信息。

  • Model層:數據層

數據可能是我們固定的死數據,更多的是來自我們服務器,從網絡上請求下來的數據。

  • VueModel層:視圖模型層

視圖模型層是View和Model溝通的橋梁。

一方面它通過Data Binding(數據綁定),將Model的改變實時的反應到View中

另一方面它通過DOM Listener(DOM監聽),當DOM發生一些事件(點擊、滾動、touch等)時,可以監聽到,並在需要的情況下改變對應的Data。

3.4 事件綁定

1.Vue如何處理事件?

  • v-on指令用法:用於綁定HTML事件,如鼠標點擊事件
  • 當前button綁定鼠標點擊事件,點擊則調用doSomething方法

在這裡doSomething() 是一個函數,可以寫在methods的方法中,供該標簽調用.

<button v-on:click="doSomething">...</button>

v-on語法糖(簡寫形式)@

<input type='button' @click='num++'/>
//06-事件基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{num}}</div>
    <div>
        //4種都可以實現
      <button v-on:click='num++'>點擊</button>
      <button @click='num++'>點擊1</button>
      <button @click='handle'>點擊2</button>
      <button @click='handle()'>點擊3</button>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        num: 0
      },
      methods: {
        handle: function () {
          // 這裡的this是Vue的實例對象
          console.log(this === vm)
          // 在函數中 想要使用data裡面的數據 一定要加this 
          this.num++;v
        }
      }
    });
  </script>
</body>

</html>

2.事件函數的調用方式

直接綁定函數名稱

<button v-on:click='say'>Hello</button>

調用函數

<button v-on:click='say()'>Hello</button>

3.事件函數參數傳遞

事件函數參數傳遞

<button v-on:click='say('hi',$event)'>Hello</button>
//07-事件函數傳參.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <div>{{num}}</div>
        <div>
            <!-- 如果事件直接綁定函數名稱,那麼默認會傳遞事件對象作為事件函數的第一個參數 -->
            <button v-on:click='handle1'>點擊1</button>
            <!-- 2、如果事件綁定函數調用,那麼事件對象必須作為最後一個參數顯示傳遞,
                 並且事件對象的名稱必須是$event -->
            <button v-on:click='handle2(123, 456, $event)'>點擊2</button>
        </div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                num: 0
            },
            methods: {
                handle1: function(event) {
                    console.log(event.target.innerHTML)
                },
                handle2: function(p, p1, event) {
                    console.log(p, p1)
                    console.log(event.target.innerHTML)
                    this.num++;
                }
            }
        });
    </script>
</body>

</html>

在這裡插入圖片描述

4.事件修飾符

.stop 阻止冒泡

<a v-on:click.stop="handle">跳轉</a>

.prevent阻止默認行為

<a v-on:click.prevent="handle">跳轉</a>
//08-事件修飾符.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{num}}</div>
    <div @click='handle0'>
      <button @click.stop='handle1'>點擊1</button>
    </div>
    <div>
      <a href="http://www.baidu.com" @click.prevent='handle2'>百度</a>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        num: 0
      },
      methods: {
        handle0: function () {
          this.num++;
        },
        handle1: function (event) {
          // js阻止冒泡
          // event.stopPropagation();
        },
        handle2: function (event) {
          // js阻止默認行為
          // event.preventDefault();
        }
      }
    });
  </script>
</body>

</html>

未加事件修飾符:

在這裡插入圖片描述

加事件修飾符:

在這裡插入圖片描述

5.按鍵修飾符

.enter 回車鍵

<input v-on:keyup.enter='submit'>

.delete刪除鍵

<input v-on:keyup.delete='handle'>
//09-按鍵修飾符.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <form action="">
      <div>
        用戶名: <input type="text" v-on:keyup.delete='clearContent' v-model='uname'>
      </div>
      <div>
        密碼:<input type="text" v-on:keyup.enter='handleSubmit' v-model='pwd'>
      </div>
      <div>
        <input type="button" v-on:click='handleSubmit' value="提交">
      </div>
    </form>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.config.keyCodes.f1 = 113
    var vm = new Vue({
      el: '#app',
      data: {
        uname: '',
        pwd: '',
        age: 0
      },
      methods: {
        clearContent:function(){
          // 按delete鍵的時候,清空用戶名
          this.uname = '';
        },
        handleSubmit: function(){
          console.log(this.uname,this.pwd)
        }
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

6.自定義按鍵修飾符

全局config.keyCodes 對象

規則:自定義按鍵修飾符名字是自定義的,但是對應的值必須是按鍵對應event.keyCode值

Vue.config.keyCodes.f1 = 112
//10-自定義事件修飾符.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
  <script type='text/javascript' src='js/vue.js'></script>
</head>

<body>
  <div id="app">
    <input type="text" @keyup.f1='handle' v-model='msg'>
  </div>
  <script type='text/javascript'>
    Vue.config.keyCodes.f1 = 65
    const app = new Vue({
      el: "#app",
      data: {
        msg: ''
      },
      methods: {
        handle: function (event) {
          console.log(event.keyCode);
        }
      }
    })
  </script>
</body>

</html>

在這裡插入圖片描述

案例:簡單計算器

在這裡插入圖片描述

需求:實現簡單的加法計算,分別輸入數值a和數值,點擊計算按鈕,結果顯示在下面。

步驟:

  • 通過v-model指令實現數值a和數值b的綁定
  • 給計算按鈕綁定事件,實現計算邏輯
  • 將計算結果綁定到對應位置
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
  <script type='text/javascript' src='js/vue.js'></script>
</head>

<body>
  <div id="app">
    <h2>簡單計算器</h2>
    <div>數值A:<input type="text" v-model="a"></div>
    <div>數值B:<input type="text" @keyup.enter='Sum' v-model="b"></div>
    <div><button @click='Sum'>計算</button></div>
    <div>計算結果:</div>
    <div v-text='result'></div>
  </div>
  <script type='text/javascript'>
    const app = new Vue({
      el: "#app",
      data: {
        a: '',
        b: '',
        result: ''
      },
      methods: {
        Sum: function () {
          //實現計算邏輯 表單輸入默認是字符串 加this很重要
          this.result = parseInt(this.a) + parseInt(this.b)
        }
      }
    })
  </script>
</body>

</html>

在這裡插入圖片描述

3.5 屬性綁定

1.Vue如何動態處理屬性?

v-bind是處理HTML中的標簽屬性的,例如

就是一個標簽,也是一個標簽,我們綁定上的src進行動態賦值。

v-bind指令用法

<a v-bind:href='url'>跳轉</a>

縮寫形式

<a :href='url'>跳轉</a>
//12-屬性綁定基本用法.html
<!DOCTYPE html>
 <html lang="en">

 <head>
   <meta charset="UTF-8">
   <title></title>
 </head>

 <body>
   <div id="app">
     <a v-bind:href="url">百度</a>
     <button @click='handle'>切換</button>
   </div>
   <script type='text/javascript' src='js/vue.js'></script>
   <script type='text/javascript'>
     const app = new Vue({
       el: "#app",
       data: {
         url: 'http://www.baidu.com'
       },
       methods: {
         handle: function () {
           //修改url地址
           this.url = 'http://www.itcast.com'
         }
       }
     })
   </script>
 </body>

 </html>

在這裡插入圖片描述

2.v-model的低層實現原理分析

不使用v-model也可以實現雙向綁定

<input v-bind:value="msg" v-on:input="msg=$event.target.value">
//13-指令v-model的本質.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    <input type="text" v-bind:value="msg" v-on:input='handle'>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'hello'
      },
      methods: {
        handle: function(event){
          // 使用輸入域中的最新的數據覆蓋原來的數據
          this.msg = event.target.value;
        }
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

3.6 樣式綁定

1. class樣式處理

對象語法

<div v-bind:class="{ active: isActive }"></div>

數組語法

<div v-bind:class="[activeClass, errorClass]"></div>
//14-樣式綁定之class綁定對象用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type='text/css'>
    .active {
      border: 1px solid red;
      width: 100px;
      height: 100px;
    }
    .error {
      background-color: pink;
    }
  </style>
</head>

<body>
  <div id="app">
    <div :class="{active:isActive,error:isError}">測試樣式</div>
    <button @click='handle'>切換</button>
  </div>
</body>
<script type='text/javascript' src='js/vue.js'></script>
<script type='text/javascript'>
  const app = new Vue({
    el: "#app",
    data: {
      isActive: true,
      isError: true,
    },
    methods: {
      handle: function () {
        //控制isActive在true和false之間切換
        this.isActive = !this.isActive
        this.isError = !this.isError
      }
    }
  })
</script>

</html>
//15-樣式綁定之class綁定數組用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .active {
      border: 1px solid red;
      width: 100px;
      height: 100px;
    }
    .error {
      background-color: pink;
    }
  </style>
</head>
<body>
  <div id="app">
    <div v-bind:class='[activeClass, errorClass]'>測試樣式</div>
    <button v-on:click='handle'>切換</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        activeClass: 'active',
        errorClass: 'error'
      },
      methods: {
        handle: function(){
          this.activeClass = '';
          this.errorClass = '';
        }
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

//16-樣式綁定之class綁定3個細節用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .active {
      border: 1px solid red;
      width: 100px;
      height: 100px;
    }
    .error {
      background-color: orange;
    }
    .test {
      color: blue;
    }
    .base {
      font-size: 28px;
    }
  </style>
</head>
<body>
  <div id="app">
    <div v-bind:class='[activeClass, errorClass, {test: isTest}]'>測試樣式</div>
    <div v-bind:class='arrClasses'></div>
    <div v-bind:class='objClasses'></div>
    <div class="base" v-bind:class='objClasses'></div>

    <button v-on:click='handle'>切換</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      樣式綁定相關語法細節:
      1、對象綁定和數組綁定可以結合使用
      2、class綁定的值可以簡化操作
      3、默認的class如何處理?默認的class會保留
      
    */
    var vm = new Vue({
      el: '#app',
      data: {
        activeClass: 'active',
        errorClass: 'error',
        isTest: true,
        arrClasses: ['active','error'],
        objClasses: {
          active: true,
          error: true
        }
      },
      methods: {
        handle: function(){
          // this.isTest = false;
          this.objClasses.error = false;
        }
      }
    });
  </script>
</body>
</html>

2. style樣式處理

對象語法

<div v-bind:style="{ color: activeColor, fontSize: fontSize }"></div>

數組語法

<div v-bind:style="[baseStyles, overridingStyles]"></div>
//17-樣式綁定之style綁定用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>

</head>

<body>
  <div id="app">
    <div v-bind:style='{border: borderStyle, width: widthStyle, height: heightStyle}'></div>
    <div v-bind:style='objStyles'></div>
    <div v-bind:style='[objStyles, overrideStyles]'></div>
    <button v-on:click='handle'>切換</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        borderStyle: '1px solid blue',
        widthStyle: '100px',
        heightStyle: '200px',
        objStyles: {
          border: '1px solid green',
          width: '200px',
          height: '100px'
        },
        overrideStyles: {
          border: '5px solid orange',
          backgroundColor: 'blue'
        }
      },
      methods: {
        handle: function () {
          this.heightStyle = '100px';
          this.objStyles.width = '100px';
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

3.7 分支循環結構

1.分支結構

  • v-if
  • v-else
  • v-else-if
  • v-show

2.v-if與v-show的區別

  • v-if控制元素是否渲染到頁面
  • v-show控制元素是否顯示(已經渲染到瞭頁面)
  • v-if當條件為false時,壓根不會有對應的元素在DOM中。v-show當條件為false時,僅僅是將元素的display屬性設置為none而已
  • 當需要在顯示與隱藏之間切換很頻繁時,使用v-show.當隻有一次切換時,通過使用v-if
//18-分支結構.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  
</head>
<body>
  <div id="app">
    <div v-if='score>=90'>優秀</div>
    <div v-else-if='score<90&&score>=80'>良好</div>
    <div v-else-if='score<80&&score>60'>一般</div>
    <div v-else>比較差</div>
    <div v-show='flag'>測試v-show</div>
    <button v-on:click='handle'>點擊</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*v-show的原理:控制元素樣式是否顯示 display:none*/
    var vm = new Vue({
      el: '#app',
      data: {
        score: 10,
        flag: false
      },
      methods: {
        handle: function(){
          this.flag = !this.flag;
        }
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

3.循環結構

  • v-for遍歷數組 v-for的語法類似於JavaScript中的for循環。格式如下:item in items的形式。

其中item為自定義屬性(改為abc都行),items為需要遍歷的數據,index為索引

<li v-for='item in list'>{{item}}</li>
<li v-for='(item,index) in list'>{{item}} + '---' +{{index}}</li>

key的作用:幫助Vue區分不同的元素對開發功能沒有效果,僅僅幫助vue提高性能,要確保key的唯一性

<li :key='item.id' v-for='(item,index) in list'>{{item}} + '---' {{index}}</li>
//19-循環結構-遍歷數組.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  
</head>
<body>
  <div id="app">
    <div>水果列表</div>
    <ul>
      <li v-for='item in fruits'>{{item}}</li>
      <li v-for='(item, index) in fruits'>{{item + '---' + index}}</li>
      <li :key='item.id' v-for='(item, index) in myFruits'>
        <span>{{item.ename}}</span>
        <span>-----</span>
        <span>{{item.cname}}</span>
      </li>

    </ul>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        fruits: ['apple', 'orange', 'banana'],
        myFruits: [{
          id: 1,
          ename: 'apple',
          cname: '蘋果'
        },{
          id: 2,
          ename: 'orange',
          cname: '橘子'
        },{
          id: 3,
          ename: 'banana',
          cname: '香蕉'
        }]
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

4. 循環結構

v-for遍歷對象

<div v-for='(value, key, index) in object'></div> value值 key鍵 index索引

v-if和v-for結合使用

<div v-if='value==12' v-for='(value, key, index) in object'></div>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>

</head>

<body>
  <div id="app">
    <div v-if='v==13' v-for='(value,key,index) in obj'>{{value + '---' + key + '---' + index}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        obj: {
          uname: 'zhangsan',
          age: 13,
          gender: 'female'
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

3.8 v-model、v-on、v-bind使用說明

v-model

v-model指令來實現表單標簽內容的雙向綁定.如表單元素和數據的雙向綁定

v-model隻能用於表單類型,就是輸入性控件,其他控件不能用,用v-bind

一個input標簽綁定瞭msg這個變量,那麼隻要input輸入發生改變,msg的值也就跟著改變,反過來也是一樣,這種綁定是雙向綁定

<input type='text' v-model='msg'>

v-on

v-on指令用法:用於綁定HTML事件,如鼠標點擊事件

當前button綁定鼠標點擊事件,點擊則調用doSomething方法

 <button v-on:click="doSomething">...</button>

v-bind

v-bind是處理HTML中的標簽屬性的,默認情況下標簽自帶屬性的值是固定的,在為瞭能夠動態的給這些屬性添加值,可以使用v-bind 例如是一個標簽,我們綁定上的src進行動態賦值。

<img :src='msg'>

4. 基礎案例:Tab選項卡

步驟:

1.實現靜態UI效果

用傳統的方式實現標簽結構和樣式

2.基於數據重構UI效果

將靜態的結構和樣式重構為基於Vue模板語法的形式

處理事件綁定和js控制邏輯

3.聲明式編程

模板的結構和最終顯示的效果基本一致

在這裡插入圖片描述

//21-選項卡案例.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .tab ul {
      overflow: hidden;
      padding: 0;
      margin: 0;
    }

    .tab ul li {
      box-sizing: border-box;
      padding: 0;
      float: left;
      width: 100px;
      height: 45px;
      line-height: 45px;
      list-style: none;
      text-align: center;
      border-top: 1px solid blue;
      border-right: 1px solid blue;
      cursor
    }

    .tab ul li:first-child {
      border-left: 1px solid blue;
    }

    .tab ul li.active {
      background-color: orange;
    }

    .tab div {
      width: 500px;
      height: 300px;
      display: none;
      text-align: center;
      font-size: 30px;
      line-height: 300px;
      border: 1px solid blue;
      border-top: 0px;
    }

    .tab div.current {
      display: block;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="tab">
      <ul>
        <li @click='change(index)' :class='currentIndex==index?"active":""' :key=' item.id'
          v-for='(item,index) in list'>
          {{item.title}}</li>
      </ul>
      <div :class='currentIndex==index?"current":""' :key='item.id' v-for='(item,index) in list'>
        <img :src="item.path">
      </div>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        currentIndex: 0, //選項卡當前的索引
        list: [{
            id: 1,
            title: 'apple',
            path: 'img/apple.png'
          },
          {
            id: 2,
            title: 'orange',
            path: 'img/orange.png'
          }, {
            id: 3,
            title: 'lemon',
            path: 'img/lemon.png'
          }
        ]
      },
      methods: {
        change: function (index) {
          //在這裡實現選項卡切換操作:操作類名,通過currentIndex
          this.currentIndex = index;
        }
      }
    })
  </script>
</body>

</html>

在這裡插入圖片描述

5. Vue常用特性

 5.1 常用特性概覽

  • 表單操作
  • 自定義指令
  • 計算屬性
  • 過濾器
  • 偵聽器
  • 生命周期

 5.2 表單操作

1.基於Vue的表單操作

  • Input單行文本
  • textarea多行文
  • select 下拉多選
  • radio 單選框
  • checkbox多選框

在這裡插入圖片描述

//01-表單基本操作.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style type="text/css">
      form div {
        height: 40px;
        line-height: 40px;
      }
      form div:nth-child(4) {
        height: auto;
      }
      form div span:first-child {
        display: inline-block;
        width: 100px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <form action="http://www.baidu.com">
        <div>
          <span>姓名:</span>
          <span>
            <input type="text" v-model="uname" />
          </span>
        </div>
        <div>
          <span>性別:</span>
          <span>
            <input type="radio" id="male" value="1" v-model="gender" />
            <label for="male">男</label>
            <input type="radio" id="female" value="2" v-model="gender" />
            <label for="female">女</label>
          </span>
        </div>
        <div>
          <span>愛好:</span>
          <input type="checkbox" id="ball" value="1" v-model="hobby" />
          <label for="ball">籃球</label>
          <input type="checkbox" id="sing" value="2" v-model="hobby" />
          <label for="sing">唱歌</label>
          <input type="checkbox" id="code" value="3" v-model="hobby" />
          <label for="code">寫代碼</label>
        </div>
        <div>
          <span>職業:</span>
          <select v-model="occupation" multiple>
            <option value="0">請選擇職業</option>
            <option value="1">教師</option>
            <option value="2">軟件工程師</option>
            <option value="3">律師</option>
          </select>
        </div>
        <div>
          <span>個人簡介:</span>
          <textarea v-model="desc"></textarea>
        </div>
        <div>
          <input type="submit" value="提交" @click.prevent="handle" />
        </div>
      </form>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      var vm = new Vue({
        el: "#app",
        data: {
          uname: "",
          gender: "", //單選為值
          hobby: [""], //多選為數組
          occupation: [""],
          desc: "",
        },
        methods: {
          handle: function () {},
        },
      });
    </script>
  </body>
</html>

在這裡插入圖片描述

2.表單域修飾符

  • number:表單輸入的字符串轉化為數值
  • trim:去掉開始和結尾的空格
  • lazy:將input事件切換為change事件 input事件立即觸發 change事件失去焦點觸發
<input v-model.number='age' type='number'
//02-表單域修飾符用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <input type="text" v-model.number='age'>
    <input type="text" v-model.trim='info'>
    <input type="text" v-model.lazy='msg'>
    <div>{{msg}}</div>
    <button @click='handle'>點擊</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        age: '',
        info: '',
        msg: ''
      },
      methods: {
        handle: function () {
          console.log(this.age + 1)
          console.log(this.info.length)
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

5.3 自定義指令

1.為何需要自定義指令?

內置指令不滿足需求

2.自定義指令的語法規則(獲取元素焦點)

//註冊一個全局自定義指令'v-focus' 
//focus為指令名稱  調用時加v-
Vue.directive('focus'{
    //當被綁定非的元素插入到DOM中時調用
	inserted:function(el){
	//獲取元素的焦點
	el.focus()
	}
})

3.自定義指令用法

<input type="text" v-focus>

一個指令定義對象可以提供如下幾個鉤子函數(均為可選):

  • bind:隻調用一次,指令第一次綁定到元素時調用,在這裡可以進行一次性的初始化設置。
  • inserted:被綁定元素插入父節點時調用(僅保證父節點存在,但不一定已被插入文檔中)。

指令鉤子函數會被傳入以下參數:

e1:指令所綁定的元素,可以用來直接操作DOM.

binding:一個對象,包含以下屬性:

  • name:指令名,不包括v-前綴。
  • value:指令的綁定值,例如:v-my-directive=”1 + 1″中,綁定值為2
  • oldvalue:指令綁定的前一個值,僅在update和componentUpdated鉤子中可用。無論值是否改變都可用。
//03-自定義指令基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <input type="text" v-focus>
    <input type="text">
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.directive('focus', {
      inserted: function (el) {
        // el表示指令所綁定的元素
        el.focus();
      }
    });
    var vm = new Vue({
      el: '#app',
      data: {

      },
      methods: {
        handle: function () {

        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

4.帶參數的自定義指令(改變元素背景色)

Vue.directive('color',{
	inserted:function(el,binding){
		el.style.backgroundColor =binding.value.color;
	}
})

5.指令的用法

<input type="text" v-color='{color:'orange'}'>
//04-帶參數的自定義指令.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
</head>

<body>
  <div id="app">
    <input type="text" v-color='msg'>
  </div>
  <script type='text/javascript' src='js/vue.js'></script>
  <script type='text/javascript'>
    Vue.directive('color', {
      bind: function (el, binding) {
        //根據指令的參數設置背景色
        el.style.backgroundColor = binding.value.color
      }
    });
    const app = new Vue({
      el: "#app",
      data: {
        msg: {
          color: 'pink'
        }
      },
      methods: {}
    })
  </script>
</body>

</html>

在這裡插入圖片描述

6.局部指令:隻能在本組件中使用

directives:{
	focus:{
	//指令的定義
	inserted:function(el){
	el.focus()
		}
	}
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" v-color='msg'>
    <input type="text" v-focus>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: {
          color: 'red'
        }
      },
      methods: {
        handle: function(){
          
        }
      },
      directives: {
        color: {
          bind: function(el, binding){
            el.style.backgroundColor = binding.value.color;
          }
        },
        focus: {
          inserted: function(el) {
            el.focus();
          }
        }
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

5.4 計算屬性

1.為何需要計算屬性?

Vue中的computed屬性被稱為計算屬性,計算屬性是寫在實例的computed選項

表達式的計算邏輯可能會比較復雜,使用計算屬性可以使模板內容更加簡介

2.計算屬性的用法

computed: {
        reverseString: function(){
          return this.msg.split('').reverse().join('');
        }
 }
//06-計算屬性基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{msg}}</div>
    <div>{{reverseString}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'nihao'
      },
      computed: {
        reverseString: function () {
            //return不要忘記
          return this.msg.split('').reverse().join('');
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

3.計算屬性和方法的區別

  • 計算屬性是基於它們的依賴進行緩存,如果多次使用時,計算屬性隻會調用一次,性能上計算屬性明顯比methods好,如果依賴改變則重新緩存
  • 方法不緩存
//07-計算屬性與方法的區別.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{reverseString}}</div>
    <div>{{reverseString}}</div>
    <div>{{reverseMessage()}}</div>
    <div>{{reverseMessage()}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Nihao',
        num: 100
      },
      methods: {
        reverseMessage: function () {
          console.log('methods')
          return this.msg.split('').reverse().join('');
        }
      },
      computed: {
        reverseString: function () {
          console.log('computed')
          return this.msg.split('').reverse().join('');
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

5.5 偵聽器

在這裡插入圖片描述

1. 偵聽器的應用場景

數據變化時執行異步或開銷較大(比較耗時)的操作

2.偵聽器的用法

watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName;
        },
        LastName: function (val) {
          this.fullName = this.firstName + ' ' + val;
        },
    }
//08-偵聽器基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>
      <span>名:</span>
      <span>
        <input type="text" v-model='firstName'>
      </span>
    </div>
    <div>
      <span>姓:</span>
      <span>
        <input type="text" v-model='lastName'>
      </span>
    </div>
    <div>{{fullName}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        firstName: 'Jim',
        lastName: 'Green',
        fullName: 'Jin Green'
      },
      watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName;
        },
        LastName: function (val) {
          this.fullName = this.firstName + ' ' + val;
        },
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

案例:驗證用戶名是否可用

需求:輸入框中輸入姓名,失去焦點時驗證是否存在,如果已經存在,提示從新輸入,如果不存在,提示可以用。

需求分析:

  1. 通過v-model實現數據綁定
  2. 需要提供提示信息
  3. 需要偵聽器監聽輸入信息的變化
  4. 需要修改觸發的事件

偵聽器

1、采用偵聽器監聽用戶名的變化

2、調用後臺接口進行驗證

3、根據驗證的結果調整提示信息

//09-偵聽器案例.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>
      <span>用戶名:</span>
      <span>
        <input type="text" v-model.lazy='uname'>
      </span>
      <span>{{tip}}</span>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        uname: '',
        tip: ''
      },
      methods: {
        checkName: function (uname) {
          //調用接口,但是可以使用定時任務的方式模擬接口調用
          var that = this;
          setTimeout(function () {
            //模擬接口調用
            if (uname == 'admin') {
              that.tip = '用戶名已經存在,請更換一個';
            } else {
              that.tip = '用戶名可以使用'
            }
          }, 1000)
        }
      },
      watch: {
        uname: function (val) {
          //調用後臺接口驗證用戶名的合法性
          this.checkName(val);
          //修改提示信息
          this.tip = '正在驗證中...'
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

5.6 過濾器

1.過濾器的作用是什麼?

格式化數據,比如將字符串格式化為首字母大寫,將日期格式化為指定的格式等

2.全局過濾器

Vue.filter('過濾器名稱',function(value){
//過濾器業務邏輯
})

3.過濾器的使用

<div>{{msg |upper}}</div>//upper為過濾器名稱
<div>{{msg |upper | lower}}</div>//級聯操作
<div :id='id | formatId'></div>

4.局部過濾器

filters:{
	upper:function(val){
        return val.charAt(0).toUpperCase() + val.slice(1);
	}
}
//10-過濾器基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <input type="text" v-model='msg'>
    <div>{{msg | upper}}</div>
    <div>{{msg | upper | lower}}</div>
    <div :abc='msg | upper'>測試數據</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.filter('lower', function (val) {
      return val.charAt(0).toLowerCase() + val.slice(1);
    });
    var vm = new Vue({
      el: '#app',
      data: {
        msg: ''
      },
      filters: {
        upper: function (val) {
          //拿到首字母將其變成大寫,然後和後面的字母拼接
          return val.charAt(0).toUpperCase() + val.slice(1);
        }
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

5.帶參數的過濾器

Vue.filter('format',function(value,arg){
	//從arg開始接收參數
})

6.過濾器的使用

<div>{{data | format('yyyy-MM-dd')}}</div>

案例:使用過濾器格式化時期

在這裡插入圖片描述

//10-過濾器基本用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{date | format('yyyy-MM-dd hh:mm:ss')}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.filter('format', function(value, arg) {
      function dateFormat(date, format) {
          if (typeof date === "string") {
              var mts = date.match(/(\/Date\((\d+)\)\/)/);
              if (mts && mts.length >= 3) {
                  date = parseInt(mts[2]);
              }
          }
          date = new Date(date);
          if (!date || date.toUTCString() == "Invalid Date") {
              return "";
          }
          var map = {
              "M": date.getMonth() + 1, //月份 
              "d": date.getDate(), //日 
              "h": date.getHours(), //小時 
              "m": date.getMinutes(), //分 
              "s": date.getSeconds(), //秒 
              "q": Math.floor((date.getMonth() + 3) / 3), //季度 
              "S": date.getMilliseconds() //毫秒 
          };

          format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
              var v = map[t];
              if (v !== undefined) {
                  if (all.length > 1) {
                      v = '0' + v;
                      v = v.substr(v.length - 2);
                  }
                  return v;
              } else if (t === 'y') {
                  return (date.getFullYear() + '').substr(4 - all.length);
              }
              return all;
          });
          return format;
      }
      return dateFormat(value, arg);
    })
    var vm = new Vue({
      el: '#app',
      data: {
        date: new Date()
      }
    });
  </script>
</body>
</html>

在這裡插入圖片描述

5.7 Vue生命周期

生命周期:事物從誕生到消亡的整個過程

vue的生命周期:每個Vue實例在被創建之前都要經過一系列的初始化過程,這個過程就是.beforeCreate()創建之前

生命周期鉤子:就是可以讓你在頁面生成的不同階段執行動作的api,作用就是隻要頁面到瞭這個階段就會觸發這個對應鉤子裡的js

1.主要階段

掛載(初始化相關屬性)

beforeCreatecreatedbeforeMountmounted

更新(元素或組件的變更操作)

beforeUpdateupdated

銷毀(銷毀相關屬性)

beforeDestroydestroyed

2.Vue實例的產生過程

  • eforeCreate在實例初始化之後,數據觀測和事件配置之前被調用。
  • created在實例創建完成後被立即調用。
  • beforeMount在掛截開始之前被調用。
  • mounted el被新創建的vm.Sel替換,並掛載到實例上去之後調用該鉤子。
  • beforeUpdate數據更新時調用,發生在虛擬DOM打補丁之前。
  • updated由於數據更改導致的虛擬DOM重新渲染和打補丁,在這之後會調用該鉤子
  • beforeDestroy實例銷毀之前調用。
  • destroyed實例銷段後調用。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-biZCGRVM-1620742265770)(Vue全傢桶之Vue基礎.assets/5.15.png)]

6.綜合案例:圖書管理

案例:圖書管理

在這裡插入圖片描述

案例:補充知識

1.數組相關API:變異方法(修改數組)

  • push()
  • pop()末尾刪除
  • shift()
  • unshift()
  • splice()刪除指定元素
  • sort()排序
  • reverse()

2.數組相關API:替換數組(生成新的數組)

  • filter()
  • concat()
  • slice()從已有的數組中選定元素,返回一個新的數組

3.數組響應式變化:修改響應數據

  • Vue.set(vm.items,indexOfltem,newValue)
  • vm.$set(vm.items,indexOfltem,newValue)

參數一表示要處理的數組名稱
參數二表示要處理的數組的索引/對象的屬性名
參數三表示要處理的數組的值

1.圖書列表

  • 實現靜態列表效果
  • 基於數據實現模板效果
  • 處理每行的操作按鈕

在這裡插入圖片描述

2.添加圖書

  • 實現表單的靜態效果
  • 添加圖書表單域數據綁定
  • 添加按鈕事件綁定
  • 實現添加業務邏輯

3.修改圖書

  • 修改信息填充到表單
  • 修改後重新提交表單
  • 重用添加和修改的方法

在這裡插入圖片描述

4.刪除圖書

刪除按鈕綁定事件處理方法

實現刪除業務邏輯

在這裡插入圖片描述

5.常用特性應用場景

過濾器(格式化日期)自定義指令(獲取表單焦點)計算屬性(統計圖書總數)偵聽器(驗證圖書存在性)生命周期(圖書數據處理)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <!-- css樣式 -->
  <style type="text/css">
    .grid {
      margin: auto;
      width: 530px;
      text-align: center;
    }

    .grid table {
      border-top: 1px solid #C2D89A;
      width: 100%;
      border-collapse: collapse;
    }

    .grid th,
    td {
      padding: 10;
      border: 1px dashed #F3DCAB;
      height: 35px;
      line-height: 35px;
    }

    .grid th {
      background-color: #F3DCAB;
    }

    .grid .book {
      padding-bottom: 10px;
      padding-top: 5px;
      background-color: #F3DCAB;
    }

    .grid .total {
      height: 30px;
      line-height: 30px;
      background-color: #F3DCAB;
      border-top: 1px solid #C2D89A;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="grid">
      <div>
        <h1>圖書管理</h1>
        <!--二、添加圖書 -->
        <div class="book">
          <div>
            <!-- 2.1添加圖書表單域數據綁定 -->
            <label for="id">
              編號:
            </label>
            <input type="text" id="id" v-model='id' :disabled="flag" v-focus>
            <label for="name">
              名稱:
            </label>
            <input type="text" id="name" v-model='name'>
            <!--2.2添加按鈕事件綁定 -->
            <button @click='handle' :disabled="submitFlag">提交</button>
          </div>
        </div>
      </div>
      <div class="total">
        <span>圖書總數:</span>
        <span>{{total}}</span>
      </div>
      <!-- 一、圖書列表 -->
      <table>
        <thead>
          <tr>
            <th>編號</th>
            <th>名稱</th>
            <th>時間</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <!-- 1.1基於數據實現模板效果 -->
          <tr :key='item.id' v-for='item in books'>
            <td>{{item.id}}</td>
            <td>{{item.name}}</td>
            <!-- 調用日期格式化過濾器 -->
            <td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td>
            <td>
              <!-- 1.2處理按鈕操作:禁止標簽跳轉 -->
              <!-- 三、修改圖書 -->
              <!-- 3.1修改按鈕綁定事件處理方法 -->
              <a href="" @click.prevent='toEdit(item.id)'>修改</a>
              <span>|</span>
              <!-- 四、刪除圖書 -->
              <!-- 4.1刪除按鈕綁定事件處理方法 -->
              <a href="" @click.prevent='deleteBook(item.id)'>刪除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    // 六、自定義指令(獲取表單焦點)
    Vue.directive('focus', {
      inserted: function (el) {
        el.focus();
      }
    });
    // 五、過濾器(格式化日期)
    Vue.filter('format', function (value, arg) {
      function dateFormat(date, format) {
        if (typeof date === "string") {
          var mts = date.match(/(\/Date\((\d+)\)\/)/);
          if (mts && mts.length >= 3) {
            date = parseInt(mts[2]);
          }
        }
        date = new Date(date);
        if (!date || date.toUTCString() == "Invalid Date") {
          return "";
        }
        var map = {
          "M": date.getMonth() + 1, //月份 
          "d": date.getDate(), //日 
          "h": date.getHours(), //小時 
          "m": date.getMinutes(), //分 
          "s": date.getSeconds(), //秒 
          "q": Math.floor((date.getMonth() + 3) / 3), //季度 
          "S": date.getMilliseconds() //毫秒 
        };
        format = format.replace(/([yMdhmsqS])+/g, function (all, t) {
          var v = map[t];
          if (v !== undefined) {
            if (all.length > 1) {
              v = '0' + v;
              v = v.substr(v.length - 2);
            }
            return v;
          } else if (t === 'y') {
            return (date.getFullYear() + '').substr(4 - all.length);
          }
          return all;
        });
        return format;
      }
      return dateFormat(value, arg);
    })
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false,
        submitFlag: false,
        id: '',
        name: '',
        books: []
      },
      methods: {
        handle: function () {
          if (this.flag) {
            // 3.3修改後重新提交表單
            // 就是根據當前的ID去更新數組中對應的數據
            this.books.some((item) => {
              if (item.id == this.id) {
                item.name = this.name;
                // 完成更新操作之後,需要終止循環
                return true;
              }
            });
            //重新提交表單之後把ID放開
            this.flag = false;
          } else {
            // 2.3實現添加業務邏輯
            // 添加圖書
            var book = {};
            book.id = this.id;
            book.name = this.name;
            book.date = 2525609975000;
            this.books.push(book);
          }
          // 表單提交後清空表單
          this.id = '';
          this.name = '';
        },
        // 3.2修改按鈕事件處理方法
        toEdit: function (id) {
          // 禁止修改ID 根據ID修改數據,一旦改變就無法確認更改那條數據
          this.flag = true;
          console.log(id)
          // 根據ID查詢出要編輯的數據
          var book = this.books.filter(function (item) {
            return item.id == id;
          });
          console.log(book)
          // 把獲取到的信息填充到表單
          this.id = book[0].id;
          this.name = book[0].name;
        },
        // 4.2刪除按鈕事件處理方法
        deleteBook: function (id) {
          // 根據id從數組中查找元素的索引
          var index = this.books.findIndex(function (item) {
            return item.id == id;
          });
          // 根據索引刪除數組元素 
          // index刪除元素的索引 1為刪除個數
          this.books.splice(index, 1);
        }
      },
      // 七、計算屬性(統計圖書總數)
      computed: {
        total: function () {
          return this.books.length;
        }
      },
      // 八、偵聽器(驗證圖書存在性)
      watch: {
        name: function (val) {
          // 驗證圖書名稱是否已經存在
          //some()判斷數組中有無滿足數據
          var flag = this.books.some(function (item) {
            return item.name == val;
          });
          if (flag) {
            // 圖書名稱存在 禁用提交按鈕
            this.submitFlag = true;
          } else {
            // 圖書名稱不存在 放開提交按鈕,可以提交
            this.submitFlag = false;
          }
        }
      },
      // 九、生命周期(圖書數據處理)
      mounted: function () {
        // 該生命周期鉤子函數被觸發的時候,模板已經可以使用
        // 一般此時用於獲取後臺數據,然後把數據填充到模板
        var data = [{
          id: 1,
          name: '三國演義',
          date: 2525609975000
        }, {
          id: 2,
          name: '水滸傳',
          date: 2525609975000
        }, {
          id: 3,
          name: '紅樓夢',
          date: 2525609975000
        }, {
          id: 4,
          name: '西遊記',
          date: 2525609975000
        }];
        this.books = data;
      }
    });
  </script>
</body>

</html>

在這裡插入圖片描述

以上就是Vue全傢桶入門基礎教程的詳細內容,更多關於Vue全傢桶入門的資料請關註WalkonNet其它相關文章!

推薦閱讀: