vue基礎

2020-08-08 17:55:01

Vue概述

vue:漸進式javascript框架

宣告式渲染->元件系統->用戶端路由->集中式狀態管理->專案構建

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

Vue基本使用

傳統開發模式對比

原生js

   <div id="msg"></div>
    <script type="text/javascript">
        var msg = 'Hello World';
        var div = document.getElementById('msg');
        div.innerHTML = msg;
    </script>

輸出

Hello World

jQuery

  <div id="msg"></div>
    <script type="text/javascript" src="./js/jquery.min.js"></script>
    <script type="text/javascript">
        var msg = 'Hello World';
        $('#msg').html(msg);
    </script>

輸出

Hello World

Vue.js之實現Hello World的基本步驟

Vue基本使用步驟

1.需要提供標籤用於填充數據

2.引入vue.js庫檔案

3.可以使用vue的語法做功能了

4.把vue提供的數據填充到標籤裏面

 <div id="app">
        <div>{{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'
            }
        });

輸出

Hello Vue
Vue.js之Hello World細節分析

1.範例參數分析

  • el:元素掛載的位置(值可以是CSS選擇器或者DOM元素)
  • data:模型數據(值是一個物件)

2.插值表達式用法

  • 將數據填充到HTML標籤中
  • 插值表達式支援基本的計算操作
    <div id="app">
        <div>{{1+2}}</div>3
        <div>{{3*8}}</div>24
        <div>{{msg + '---' + 123}}</div>Hello Vue---123
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'Hello Vue'
            }
        });
    </script>

3.Vue程式碼執行原理分析

  • 概述編譯過程的概念(Vue語法->原生語法。vue程式碼通過vue框架編譯成原生js程式碼)

Vue模板語法

如何理解前端渲染

把數據填充到HTML標籤中

在这里插入图片描述

前端渲染的方式

  • 原生js拼接字串

基本上就是將數據以字串的方式拼接到HTML標籤中

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

  • 使用前端模板引擎

與字串拼接相比,程式碼明顯規範了很多,它擁有自己的一套模板語法規則

優點:大家都遵循同樣的規則寫程式碼,程式碼可讀性明顯提高了,方便後期維護

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

  • 使用vue特有的模板語法
模板語法概覽
插值表達式
指令

1.什麼是指令

  • 指令的本質式自定義屬性
  • 指令的格式:以v-開始(比如:v-cloak)

2.v-cloak指令用法

  • 插值表達式存在的問題:「閃動」
  • 如何解決該問題:使用v-cloak指令
  • 解決該問題的原理:先隱藏,替換好值之後再顯示最終的值
<style>
        [v-cloak] {
            display: none;
        }
 </style>
 <div id="app">
        <div v-cloak>{{msg}}</div>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        // v-cloak指令用法
        // 1.提供樣式
        // [v-cloak]{
        //     display:none;
        // }
        // 2.在插值表達式所在的標籤中新增v-cloak指令
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'Hello Vue'
            }
        });
    </script>

數據系結指令

  • v-text 填充純文字
  1. 相比插值表達式更加簡潔
  2. 沒有「閃動」問題
   <div id="app">
        <div v-text="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'
            }
        });

輸出

Hello Vue
  • v-html 填充HTML片段
  1. 存在安全問題
  2. 本網站內部數據可以使用,來自第三方的數據不可用
  3. 能識別html標籤
    <div id="app">
        <div v-html="msg1"></div>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                msg1: '<h1>HTML</h1>'
            }
        });
    </script>

輸出

HTML
  • v-pre 填充原始資訊
  1. 顯示原始資訊,跳過編譯過程(分析編譯過程)
  <div id="app">
        <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 World'
            }
        });

輸出

{{msg}}

數據響應式

  • 如何理解響應式
  1. html5中的響應式(螢幕尺寸的變化導致樣式的變化)
  2. 數據的響應式(數據的變化導致頁面內容的變化)
  • 什麼是數據系結
  1. 數據系結:將數據填充到標籤中
  • v-once 只編譯一次
  1. 顯示內容之後不再具有響應式功能
  2. 應用場景:如果顯示的資訊後續不需要修改,可以使用v-once,這樣可以提高效能
    <div id="app">
        <div v-once>{{info}}</div>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                info: 'nihao'
            }
        });
    </script>

雙向數據系結

數據的變化導致頁面內容的變化,頁面內容的變化導致數據的變化

  • v-model指令用法
    <div id="app">
        <div>{{info}}</div>
        <div>
            <input type="text" v-model="info">
        </div>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                info: 'nihao'
            }
        });
    </script>

MVVM設計思想

  1. M(model)
  2. V(view)
  3. VM(View-Model)
事件系結

vue處理事件

  • v-on指令用法
    <div id="app">
        <div>{{num}}</div>
        <div>
            <button v-on:click="num++">點選</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
            }
        });
    </script>
  • v-on簡寫形式
  <div id="app">
        <div>{{num}}</div>
        <div>
            <button @click="num++">點選1</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
            }
        });
    </script>

事件函數的呼叫方式

  • 直接系結函數名稱
    <div id="app">
        <div>{{num}}</div>
        <div>
            <button @click="handle">點選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: {
                handle: function () {
                    //這裏的this是Vue的範例物件
                    console.log(this == vm); //true
                    this.num++;
                }
            }
        });
    </script>
  • 呼叫函數
    <div id="app">
        <div>{{num}}</div>
        <div>
            <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); //true
                    this.num++;
                }
            }
        });
    </script>

事件函數的參數傳遞

  • 直接系結函數名稱方式
    <div id="app">
        <div>{{num}}</div>
        <div>
            <button @click="handle1">系結事件函數名稱方式</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.tagName);//BUTTON
                    console.log(event.target.innerHTML);//系結事件函數名稱方式
                }
            }
        });
    </script>
  • 呼叫函數方式
    <div id="app">
        <div>{{num}}</div>
        <div>
            <button @click="handle2(123,456,$event)">呼叫函數方式</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: {
                handle2: function (p1, p2, event) {
                    console.log(p1); //123
                    console.log(p2); //456
                    console.log(event.target.tagName); //BUTTON
                    console.log(event.target.innerHTML);//呼叫函數方式
                }
            }
        });
    </script>

事件修飾符

1.阻止冒泡

   <div id="app">
        <div>{{num}}</div>
        <div @click="handle0">
            <button @click.stop="handle1">點選1</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: {
                handle0: function () {
                    this.num++;
                },
                handle1:function(event){
                    // 原生js阻止冒泡
                    // event.stopPropagation();
                }

            }
        });
    </script>

2.阻止預設行爲

   <div id="app">
        <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: {
                handle2: function (event) {
                    //    原生js阻止預設行爲
                    // event.preventDefault();
                }

            }
        });
    </script>

按鍵修飾符

1.enter鍵

    <div id="app">
        <form action="">
            <div>
                使用者名稱:<input type="text" v-model="uname">
            </div>
            <div>
                密碼:<input type="text" v-on:keyup.enter="handleSubmit" v-model="pwd">
            </div>
            <div>
                <input type="button" @click="handleSubmit" value="提交">
            </div>
        </form>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                uname: '',
                pwd: ''
            },
            methods: {
                handleSubmit: function () {
                    console.log(this.uname, this.pwd);
                }
            }
        });
    </script>

2.delete鍵

    <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" @click="handleSubmit" value="提交">
            </div>
        </form>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                uname: '',
                pwd: ''
            },
            methods: {
                clearContent: function () {
                    // 按delete鍵的時候,清空使用者名稱
                    this.uname = '';
                },
                handleSubmit: function () {
                    console.log(this.uname, this.pwd);
                }
            }
        });
    </script>

自定義按鍵修飾符

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

    <div id="app">
        <input type="text" v-on:keyup.aaa="handle" v-model="info">
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        Vue.config.keyCodes.aaa = 65
        var vm = new Vue({
            el: '#app',
            data: {
                info: ''
            },
            methods: {
                handle: function (event) {
                    console.log(event.keyCode);//65
                }
            }
        });
    </script>

案例:簡單計算器

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

分析:

1.通過v-model指令實現數值a和數值b的系結

2.給計算按鈕系結事件,實現計算邏輯

3.將計算結果系結到對應位置

   <div id="app">
        <h1>簡單計算器</h1>
        <div>
            <span>數值A:</span>
            <span>
                <input type="text" v-model="a">
            </span>
        </div>
        <div>
            <span>數值B:</span>
            <span>
                <input type="text" v-model="b">
            </span>
        </div>
        <div>
            <button v-on:click="handle">計算</button>
        </div>
        <div>
            <span>計算結果</span>
            <span v-text="result"></span>
        </div>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                a: '',
                b: '',
                result: ''
            },
            methods: {
                handle: function () {
                    //實現計算邏輯
                    this.result = parseInt(this.a) + parseInt(this.b);
                }
            }
        });
    </script>
屬性系結

Vue動態處理屬性

  • v-bind指令用法
<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">
        var vm = new Vue({
            el: '#app',
            data: {
                url: 'http://www.baidu.com'
            },
            methods: {
                handle: function () {
                    // 修改URL地址
                    this.url = 'http://www.jd.com'
                }
            }
        });
    </script>
  • 縮寫形式
    <div id="app">
        <a :href="url">百度</a>
        <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: {
                url: 'http://www.baidu.com'
            },
            methods: {
                handle: function () {
                    // 修改URL地址
                    this.url = 'http://www.jd.com'
                }
            }
        });
    </script>

v-model的底層實現原理分析

原始版

    <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>

升級版

   <div id="app">
        <div>{{msg}}</div>
        <input type="text" v-bind:value="msg" v-on:input="msg=$event.target.value">
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'hello'
            },
            methods: {

            }
        });
    </script>

最終版

    <div id="app">
        <div>{{msg}}</div>
        <input type="text" v-model="msg">
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'hello'
            },
            methods: {

            }
        });
    </script>
樣式系結

1.class樣式處理

  • 物件語法
    <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }

        .error {
            background-color: orange;
        }
    </style>
    <div id="app">
        <div v-bind:class="{active:isActive,error:isError}">測試內容</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: {
                isActive: true,
                isError: true
            },
            methods: {
                handle: function () {
                    // 控制isActive在true和false之間切換
                    this.isActive = !this.isActive;
                    this.isError = !this.isError;
                }
            }
        });
    </script>
  • 陣列語法
    <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }

        .error {
            background-color: orange;
        }
    </style>
    <div id="app">
        <div v-bind:class="[activeClass,errorClass]">測試內容</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: {
                activeClass: 'active',
                errorClass: 'error'
            },
            methods: {
                handle: function () {
                    this.activeClass = '';
                    this.errorClass = ''
                }
            }
        });
    </script>

樣式系結相關語法細節

1.物件系結和陣列系結可以結合使用

    <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }

        .error {
            background-color: orange;
        }

        .text {
            color: red;
        }
    </style>
     <div id="app">
        <div v-bind:class="[activeClass,errorClass,{text:isText}]">測試內容</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: {
                activeClass: 'active',
                errorClass: 'error',
                isText: true
            },
            methods: {
                handle: function () {
                    this.isText = !this.isText;
                }
            }
        });
    </script>

2.class系結的值可以簡化操作

   <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }

        .error {
            background-color: orange;
        }
    </style>
    <div id="app">
        <div v-bind:class="objClasses"></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: {
                objClasses: {
                    active: true,
                    error: true
                }
            },
            methods: {
                handle: function () {
                    this.objClasses.error = false;
                }
            }
        });
    </script>

3.預設的class如何處理?預設的class會保留

 <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }

        .error {
            background-color: orange;
        }
        .base{
            font-size: 12px;
        }
    </style>
    <div id="app">
        <div class="base" v-bind:class="objClasses"></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: {
                objClasses: {
                    active: true,
                    error: true
                }
            },
            methods: {
                handle: function () {
                    this.objClasses.error = false;
                }
            }
        });
    </script>

2.style樣式處理

  • 物件語法

方法一:

<div id="app">
        <div v-bind:style="{border:borderStyle,width:widthStyle,height:heihgtStyle}"></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',
                heihgtStyle: '100px'
            },
            methods: {
                handle: function () {
                    this.widthStyle = '200px';
                }
            }
        });
    </script>

方法二(簡化版):

<div id="app">
        <div v-bind:style="objStyles"></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: {
                objStyles: {
                    border: '1px solid red',
                    width: '100px',
                    height: '100px'
                }
            },
            methods: {
                handle: function () {
                    this.objStyles.width = '200px';
                }
            }
        });
    </script>
  • 陣列語法(原有的樣式會被覆蓋)
    <div id="app">
        <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: {
                objStyles: {
                    border: '1px solid red',
                    width: '100px',
                    height: '100px'
                },
                overrideStyles: {
                    border: '5px solid blue',
                    backgroundColor: 'orange'
                }
            },
            methods: {
                handle: function () {
                    this.objStyles.width = '200px';
                }
            }
        });
    </script>
分支回圈結構
  • v-if
  • v-else-if
  • v-else
    <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>=70">一般</div>
        <div v-else>比較差</div>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                score: 10
            },
            methods: {

            }
        });
    </script>

v-show

原理:控制元素的樣式是否顯示

<div id="app">
        <div v-show="flag">測試v-show</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: {
                flag: false
            },
            methods: {
                handle: function () {
                    this.flag = !this.flag;
                }
            }
        });
    </script>

v-if與v-show的區別

  • v-if控制元素是否渲染到頁面
  • v-show控制元素是否顯示(已經渲染到頁面)

v-for遍歷陣列

語法:

 <li v-for="item in fruits">{{item}}</li>

範例:

   <div id="app">
        <div>水果列表</div>
        <ul>
            <li v-for="item in fruits">{{item}}</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']
            }
        });
    </script>

輸出

水果列表
apple
orange
banana

複雜版:

 <div id="app">
        <div>水果列表</div>
        <ul>
            <li v-for="item 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: {
                myFruits: [{
                    ename: 'apple',
                    cname: '蘋果'
                }, {
                    ename: 'orange',
                    cname: '橘子'
                }, {
                    ename: 'banana',
                    cname: '香蕉'
                }]
            }
        });
    </script>

輸出:

水果列表
apple ---- 蘋果
orange ---- 橘子
banana ---- 香蕉

語法

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

範例:

    <div id="app">
        <div>水果列表</div>
        <ul>
            <li v-for="(item,index) in fruits">{{item+'----'+index}}</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']
            }
        });
    </script>

輸出

水果列表
apple----0
orange----1
banana----2

key的作用:幫助Vue區分不同的元素,從而提高效能

<li :key="item.id" v-for="(item,index) in fruits">{{item+'----'+index}}</li>

v-for遍歷物件

語法:

<div v-for="(v,k,i) in obj">{{v+'----'+k+'----'+i}}</div>

範例:

  <div id="app">
        <div v-for="(v,k,i) in obj">{{v+'----'+k+'----'+i}}</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: 12,
                    gender: 'male'
                }
            }
        });
    </script>

輸出:

zhangsan----uname----0
12----age----1
male----gender----2

v-if與v-for結合使用

語法:

<div v-if="v==12" v-for="(v,k,i) in obj">{{v+'----'+k+'----'+i}}</div>

範例:

<div id="app">
        <div v-if="v==12" v-for="(v,k,i) in obj">{{v+'----'+k+'----'+i}}</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: 12,
                    gender: 'male'
                }
            }
        });
    </script>

輸出:

12----age----1

案例:Tab索引標签

效果:

在这里插入图片描述

程式碼:

    <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: pointer;
        }

        .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>
    <div id="app">
        <div class="tab">
            <ul>
                <li :key="item.id" @click="change(index)" :class="currentIndex==index?'active':''"
                    v-for="(item,index) in list">{{item.title}}</li>
            </ul>
            <div :key="item.id" :class="currentIndex==index?'current':''" v-for="(item,index) in list">
                <img :src="item.path" alt="">
            </div>
        </div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        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) {
                    // 在這裏實現索引標签切換操作:本質就是操作類名
                    this.currentIndex = index;
                }
            }
        })
    </script>

Vue常用特性

表單操作
  • input單行文字
 <div id="app">
        <form action="">
            <input type="text" v-model="uname">
            <input type="submit" @click.prevent="handle">
        </form>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                uname: 'lisi'
            },
            methods: {
                handle: function () {
                    console.log(this.uname);//lisi

                }
            }
        })
    </script>
  • radio無線電鈕
<div id="app">
        <form action="">
            <input type="radio" value="1" v-model="gender">男
            <input type="radio" value="2" v-model="gender">女
            <input type="submit" @click.prevent="handle">
        </form>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                gender: 2
            },
            methods: {
                handle: function () {
                    console.log(this.gender);

                }
            }
        })
    </script>
  • checkbox複選按鈕
    <div id="app">
        <form action="">
            <span>愛好</span>
            <input type="checkbox" value="1" v-model="hobby">
            <input type="checkbox" value="2" v-model="hobby">
            <input type="checkbox" value="3" v-model="hobby">
            <input type="submit" @click.prevent="handle">
        </form>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                hobby:['2','3']
            },
            methods: {
                handle: function () {
                    console.log(this.hobby);//["2", "3", __ob__: Observer]
                    // console.log(this.hobby.toString());//2,3

                }
            }
        })
    </script>
  • select下拉選單

單選

<div id="app">
        <form action="">
            <span>職業</span>
            <select v-model="occupation">
                <option value="0">請選擇職業...</option>
                <option value="1">教師</option>
                <option value="2">軟體工程師</option>
                <option value="3">律師</option>
            </select>
            <input type="submit" @click.prevent="handle">
        </form>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                occupation: 1
            },
            methods: {
                handle: function () {
                    console.log(this.occupation);

                }
            }
        })
    </script>

多選

<div id="app">
        <form action="">
            <span>職業</span>
            <select v-model="occupation" multiple>
                <option value="0">請選擇職業...</option>
                <option value="1">教師</option>
                <option value="2">軟體工程師</option>
                <option value="3">律師</option>
            </select>
            <input type="submit" @click.prevent="handle">
        </form>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                occupation: ['2', '3']
            },
            methods: {
                handle: function () {
                    console.log(this.occupation.toString());//2,3
                }
            }
        })
    </script>
  • textarea文字域
    <div id="app">
        <form action="">
            <span>個人簡介</span>
            <textarea v-model="desc"></textarea>
            <input type="submit" @click.prevent="handle">
        </form>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                desc: 'nihao'
            },
            methods: {
                handle: function () {
                    console.log(this.desc);//nihao
                }
            }
        })
    </script>

表單域修飾符

  • number:轉化爲數值
<div id="app">
        <input type="text" v-model.number="age">
        <button @click="handle">點選</button>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                age: ''
            },
            methods: {
                handle: function () {
                    console.log(this.age + 13);

                }
            }
        })
    </script>
  • trim:去掉開始和結尾空格
<div id="app">
        <input type="text" v-model.trim="info">
        <button @click="handle">點選</button>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                info: ''
            },
            methods: {
                handle: function () {
                   console.log(this.info.length);
                   

                }
            }
        })
    </script>
  • lazy:將input事件切換爲change事件(input事件當輸入的時候會觸發,change事件當滑鼠離開的時候觸發)
<div id="app">
        <input type="text" v-model.lazy="msg">
        <div>{{msg}}</div>
        <button @click="handle">點選</button>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: ''
            },
            methods: {
                handle: function () { 

                }
            }
        })
    </script>
自定義指令

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

Vue.directive('focus', {
            inserted: function (el) {
                //el表示指令所系結的元素
                el.focus();
            }
        })

自定義指令用法

<input type="text" v-focus>

範例:

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

            },
            methods: {

            }
        })
    </script>

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

<div id="app">
        <input type="text" v-color="msg">
    </div>
    <script src="./js/vue.js"></script>
    <script>
        //自定義指令
        Vue.directive('color', {
            bind: function (el, binding) {
                //根據指令的參數設定背景色
                // console.log(binding.value.color);//orange
                el.style.backgroundColor = binding.value.color;

            }
        })
        var vm = new Vue({
            el: '#app',
            data: {
                msg: {
                    color: 'orange'
                }
            },
            methods: {

            }
        })
    </script>

區域性指令

<div id="app">
        <input type="text" v-color="msg">
        <input type="text" v-focus>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: {
                    color: 'orange'
                }
            },
            methods: {

            },
            directives: {
                color: {
                    bind: function (el, binding) {
                        //根據指令的參數設定背景色
                        // console.log(binding.value.color); //orange
                        el.style.backgroundColor = binding.value.color;
                    }
                },
                focus: {
                    inserted: function (el) {
                        el.focus();
                    }
                }
            }
        })
    </script>
計算屬性

爲何需要計算屬性

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

原始做法:

    <div id="app">
        <div>{{msg}}</div>
        <div>{{msg.split('').reverse().join('')}}</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'Hello'
            },
            methods: {

            }

        })
    </script>

輸出

Hello
olleH

計算屬性做法:

    <div id="app">
        <div>{{msg}}</div>
        <div>{{reverseString}}</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'Nihao'
            },
            methods: {

            },
            computed: {
                reverseString: function () {
                    return this.msg.split('').reverse().join('');
                }
            }

        })
    </script>

輸出

Nihao
oahiN

計算屬性與方法的區別

  • 計算屬性是基於它們的依賴進行快取的
  • 方法不存在快取
<div id="app">
        <div>{{reverseString}}</div>
        <div>{{reverseString}}</div>
        <div>{{reverseMessage()}}</div>
        <div>{{reverseMessage()}}</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'Nihao'
            },
            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>

瀏覽器中輸出:

oahiN
oahiN
oahiN
oahiN

控制檯中輸出:

computed
methods
methods
偵聽器

數據一旦發生變化就通知偵聽器所系結方法

應用場景

數據變化時執行非同步或開銷較大的操作

偵聽器做法:

<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 src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                firstName: 'Jim',
                lastName: 'Green',
                fullName: 'Jim Green'
            },
            methods: {

            },
            watch: {
                firstName: function (val) {
                //val表示變化之後的值
                    this.fullName = val + '' + this.lastName
                },
                lastName: function (val) {
                    this.fullName = this.firstName + '' + val
                }
            }

        })
    </script>

輸出
在这里插入图片描述
計算屬性做法

<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 src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                firstName: 'Jim',
                lastName: 'Green',
            },
            computed: {
                fullName: function () {
                    return this.firstName + '' + this.lastName;
                }
            }

        })
    </script>

輸出:

在这里插入图片描述

偵聽器案例:驗證使用者名稱是否可用

需求:

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

需求分析:

1.通過v-model實現數據系結

2.需要提供提示資訊

3.需要偵聽器監聽輸入資訊的變化

4.需要修改觸發的事件

<div id="app">
        <div>
            <span>使用者名稱:</span>
            <span>
                <input type="text" v-model.lazy="uname">
            </span>
            <span>{{tip}}</span>
        </div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        /*
            偵聽器
            1.採用偵聽器監聽使用者名稱的變化
            2.呼叫後臺介面進行驗證
            3.根據驗證的結果調整提示資訊
        */
        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 = '使用者名稱可以使用'
                        }
                    }, 2000);
                }
            },
            watch: {
                uname: function (val) {
                    //呼叫後臺介面驗證使用者名稱的合法性
                    this.checkName(val);
                    //修改提示資訊
                    this.tip = '正在驗證...';
                }
            }

        })
    </script>
過濾器

過濾器的作用

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

自定義過濾器

用法一:

<div id="app">
        <input type="text" v-model="msg">
        <div>{{msg | upper}}</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.filter('upper', function (val) {
            return val.charAt(0).toUpperCase() + val.slice(1);
        });
        Vue.filter('lower', function (val) {
            return val.charAt(0).toLowerCase() + val.slice(1);
        });
        var vm = new Vue({
            el: '#app',
            data: {
                msg: ''
            }

        })
    </script>

方法二:

    <div id="app">
        <input type="text" v-model="msg">
        <div :abc="msg | upper">測試數據</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.filter('upper', function (val) {
            return val.charAt(0).toUpperCase() + val.slice(1);
        })
        var vm = new Vue({
            el: '#app',
            data: {
                msg: ''
            }

        })
    </script>

區域性過濾器

<div id="app">
        <input type="text" v-model="msg">
        <div :abc="msg | upper">測試數據</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: ''
            },
            filters: {
                upper: function (val) {
                    return val.charAt(0).toUpperCase() + val.slice(1);
                }
            }

        })
    </script>

帶參數的過濾器

 <div id="app">
        <div>{{date | format('yyyy-MM-dd')}}</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.filter('format', function (value, arg) {
        //value是過濾器傳遞過來的參數
            if (arg == 'yyyy-MM-dd') {
                var ret = '';
                ret += value.getFullYear() + '-' + (value.getMonth() + 1) + '-' + value.getDate();
                return ret;
            }
            return value;
        })
        var vm = new Vue({
            el: '#app',
            data: {
                date: new Date()
            },

        })
    </script>

輸出:

2020-3-15
生命週期

在这里插入图片描述

vue範例的產生過程

在这里插入图片描述

陣列相關API

1.變異方法(修改原有數據)

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

2.替換陣列(生成新的陣列)

  • filter()
  • concat()
  • slice()

範例:

<div id="app">
        <div>
            <span>
                <input type="text" v-model="fname">
                <button @click="add">新增</button>
                <button @click="del">刪除</button>
                <button @click="change">替換</button>
            </span>
        </div>
        <ul>
            <li :key="index" v-for="(item,index) in list">{{item}}</li>
        </ul>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                fname: '',
                list: ['apple', 'orange', 'banana']
            },
            methods: {
                add: function () {
                    this.list.push(this.fname);
                },
                del: function () {
                    this.list.pop();
                },
                change: function () {
                    this.list = this.list.slice(0, 2);
                }
            }

        })
    </script>
陣列響應式變化

修改響應式數據

  • Vue.set(vm.items,indexOfItem,newValue)
  • vm.$set(vm.items,indexOfItem,newValue)
  1. 參數一表示要處理的陣列的名稱
  2. 參數二表示要處理的陣列的索引
  3. 參數三表示要處理的陣列的值

Vue.set(vm.items,indexOfItem,newValue)

    <div id="app">
        <ul>
            <li :key="index" v-for="(item,index) in list">{{item}}</li>
        </ul>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                list: ['apple', 'orange', 'banana']
            }

        })
        Vue.set(vm.list, 2, 'lemon')
    </script>

vm.$set(vm.items,indexOfItem,newValue)

<div id="app">
        <div>{{info.name}}</div>
        <div>{{info.age}}</div>
        <div>{{info.gender}}</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                info: {
                    name: 'lisi',
                    age: 12,
                    gender: 'female'
                }
            }

        })
        vm.$set(vm.info, 'gender', 'male')
    </script>
案例:圖書館管理

效果如下:

在这里插入图片描述

1.圖書列表

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

2.新增圖書

  • 實現表單的靜態效果
  • 新增圖書表單域數據系結
  • 新增按鈕事件系結
  • 實現新增業務邏輯

3.修改圖書

  • 修改資訊填充到表單
  • 修改後重新提交表單
  • 重用新增和修改方法

4.刪除圖書

  • 刪除按鈕系結事件處理方法
  • 實現刪除業務邏輯

常用特性應用場景

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

案例程式碼如下:

 <style type="text/css">
        .grid {
            margin: auto;
            width: 500px;
            text-align: center;
        }

        .grid table {
            width: 100%;
            border-collapse: collapse;
        }

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

        .grid th {
            background-color: orange;
        }

        .grid .total {
            height: 30px;
            line-height: 30px;
            background-color: #F3DCAB;
            border-top: 1px solid #C2D89A;
        }
    </style>
    <div id="app">
        <div class="grid">
            <div>
                <h1>圖書管理</h1>
                <div class="book">
                    <div>
                        <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">
                        <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>
                    <tr :key='item.id' v-for='item in books'>
                        <td>{{item.id}}</td>
                        <td>{{item.name}}</td>
                        <td>{{item.date}}</td>
                        <td>
                            <a href="" @click.prevent="toEdit(item.id)">修改</a>
                            <span>|</span>
                            <a href="" @click.prevent="deleteBook(item.id)">刪除</a>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.directive('focus', {
            inserted: function (el) {
                el.focus();
            }
        })
        var vm = new Vue({
            el: '#app',
            data: {
                flag: false,
                submitFlag: false,
                id: '',
                name: '',
                books: []
            },
            methods: {
                handle: function () {
                    if (this.flag) {
                        //編輯操作
                        //就是根據當前的的ID去更新陣列中的對應的數據
                        this.books.some((item) => {
                            if (item.id == this.id) {
                                item.name = this.name;
                                //完成更新操作之後,需要終止回圈
                                return true;
                            }
                        });
                        this.flag = false;
                    } else {
                        //新增圖書
                        var book = {};
                        book.id = this.id;
                        book.name = this.name;
                        book.date = '';
                        this.books.push(book);
                        //清空表單
                        this.id = '';
                        this.name = ''
                    }
                    this.id = '';
                    this.name = ''

                },
                toEdit: function (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;

                },
                deleteBook: function (id) {
                    //刪除圖書
                    //根據id從陣列中查詢元素的索引
                    ///方法一:
                    // var index = this.books.findIndex(function (item) {
                    //     return item.id == id
                    // });
                    // //根據索引刪除陣列元素
                    // this.books.splice(index, 1);
                    ///----------------------
                    ///方法二:根據filter方法進行刪除
                    this.books = this.books.filter(function (item) {
                        return item.id != id;
                    });

                }
            },
            computed: {
                total: function () {
                    //計算圖書的總數
                    return this.books.length;
                }
            },
            watch: {
                name: function (val) {
                    //驗證圖書名稱是否已經存在
                    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: ''
                }, {
                    id: 2,
                    name: '水滸傳',
                    date: ''
                }, {
                    id: 3,
                    name: '紅樓夢',
                    date: ''
                }, {
                    id: 4,
                    name: '西遊記',
                    date: ''
                }];
                this.books = data;
            }
        });
    </script>

元件註冊

全域性元件註冊基本使用
    <div id="app">
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('button-counter', {
            data: function () {
                return {
                    count: 0
                }
            },
            template: '<button @click="handle">點選了{{count}}次</button>',
            methods: {
                handle: function () {
                    this.count += 2;
                }
            }
        })
        var vm = new Vue({
            el: '#app',
            data: {

            }
        })
    </script>

輸出

點選了2次 點選了4次 點選了6次

元件註冊注意事項

1.data必須是一個函數

2.元件模板內容必須是單個根標籤

3.元件模板內容可以是模板字串

4.如果使用駝峯式命名元件,那麼在使用元件的時候,只能在字串模板中用駝峯的方式使用元件,但是在普通的標籤模板中,必須使用短橫線的方式使用元件

區域性元件註冊基本使用
<div id="app">
        <hello-world></hello-world>
        <hello-tom></hello-tom>
        <hello-jerry></hello-jerry>

    </div>
    <script src="./js/vue.js"></script>
    <script>
        var HelloWorld = {
            data: function () {
                return {
                    msg: 'HelloWorld'
                }
            },
            template: '<div>{{msg}}</div>'
        };
        var HelloTom = {
            data: function () {
                return {
                    msg: 'HelloTom'
                }
            },
            template: '<div>{{msg}}</div>'
        };
        var HelloJerry = {
            data: function () {
                return {
                    msg: 'HelloJerry'
                }
            },
            template: '<div>{{msg}}</div>'
        }
        var vm = new Vue({
            el: '#app',
            data: {

            },
            components: {
                'hello-world': HelloWorld,
                'hello-tom': HelloTom,
                'hello-jerry': HelloJerry
            }
        })
    </script>

輸出

HelloWorld
HelloTom
HelloJerry

元件間數據互動

父元件向子元件傳值

1.元件內部通過props接收傳遞過來的值

2.父元件通過屬性將值傳遞給子元件

<div id="app">
        <div>{{pmsg}}</div>
        <menu-item title="來自父元件的值"></menu-item>
        <menu-item :title="ptitle" content="hello"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            props: ['title', 'content'],
            data: function () {
                return {
                    msg: '子元件本身的數據'
                }
            },
            template: '<div>{{msg +"-----" + title + "-----" + content}}</div>'
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
                ptitle: '動態系結屬性',
            }
        })
    </script>

輸出

父元件中的內容
子元件本身的數據-----來自父元件的值-----undefined
子元件本身的數據-----動態系結屬性-----hello
props屬性名規則
  • 在props中使用駝峯形式,在普通的模板標籤中需要使用短橫線的形式
  • 字串形式的模板中沒有這個限制
props屬性值型別
  • 字串 String
<div id="app">
        <div>{{pmsg}}</div>
        <menu-item :pstr="pstr"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            props: ['pstr'],

            template: `
                <div>
                    <div>{{pstr}}</div>
                </div>
            `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
                pstr: 'hello'
            }
        })
    </script>

輸出:

父元件中的內容
hello
  • 數值 Number
    <div id="app">
        <div>{{pmsg}}</div>
        <menu-item :pnum1="12" pnum2="13"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            props: ['pnum1','pnum2'],

            template: `
                <div>
                    <div>{{12 + pnum1}}</div>
                    <div>{{13 + pnum2}}</div>
                </div>
            `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
            }
        })
    </script>

輸出:

父元件中的內容
24
1313
  • 布爾值 Boolean
    <div id="app">
        <div>{{pmsg}}</div>
        <menu-item :pboo1="true" pboo2="true"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            props: ['pboo1', 'pboo2'],

            template: `
                <div>
                    <div>{{ typeof pboo1}}</div>
                    <div>{{typeof pboo2}}</div>
                </div>
            `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
            }
        })
    </script>

輸出

父元件中的內容
boolean
string
  • 陣列 Array
<div id="app">
        <div>{{pmsg}}</div>
        <menu-item :parr="parr"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            props: ['parr'],

            template: `
                <ul>
                    <li :key="index" v-for="(item,index) in parr">{{item}}</li>
                </ul>
            `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
                parr: ['apple', 'orange', 'banana']
            }
        })
    </script>

輸出:

父元件中的內容
apple
orange
banana
  • 物件 Object
<div id="app">
        <div>{{pmsg}}</div>
        <menu-item :pobj="pobj"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            props: ['pobj'],

            template: `
                <div>
                    <span>{{pobj.name}}</span>
                    <span>{{pobj.age}}</span>
                </div>
            `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
                pobj: {
                    name: 'zhangsan',
                    age: 12
                }
            }
        })
    </script>

輸出

父元件中的內容
zhangsan 12
子元件向父元件傳值基本用法

1.子元件通過自定義事件向父元件傳遞資訊

2.父元件監聽子元件的事件

<div id="app">
        <div :style="{fontSize:fontSize + 'px'}">{{pmsg}}</div>
        <menu-item @enlarge-text="handle"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            template: `
               <button @click='$emit("enlarge-text")'>擴大父元件中字型大小</button>
            `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
                fontSize: 10
            },
            methods: {
                handle: function () {
                    //擴大字型大小
                    this.fontSize += 5;
                }
            }
        })
    </script>

子元件向父元件傳值–攜帶參數

<div id="app">
        <div :style="{fontSize:fontSize + 'px'}">{{pmsg}}</div>
        <menu-item @enlarge-text="handle($event)"></menu-item>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('menu-item', {
            template: `
               <button @click='$emit("enlarge-text",10)'>擴大父元件中字型大小</button>
            `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
                fontSize: 10
            },
            methods: {
                handle: function (val) {
                    //擴大字型大小
                    this.fontSize += val
                }
            }
        })
    </script>
非父子元件間傳值

在这里插入图片描述

1.單獨的事件中心管理元件間的通訊

2.監聽事件與銷燬事件

     <div id="app">
        <div>父元件</div>
        <div>
            <button @click="handle">銷燬</button>
        </div>
        <test-tom></test-tom>
        <test-jerry></test-jerry>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        //提供事件中心
        var hub = new Vue();
        Vue.component('test-tom', {
            data: function () {
                return {
                    num: 0
                }
            },
            template: `
               <div>
                    <div>TOM:{{num}}</div>
                    <div>
                        <button @click='handle'>點選</button>
                    </div>
               </div>
            `,
            methods: {
                handle: function () {
                    //觸發兄弟元件的事件
                    hub.$emit('jerry-event', 2)
                }
            },
            mounted: function () {
                //監聽事件
                //val是兄弟元件傳遞過來的
                hub.$on('tom-event', (val) => {
                    this.num += val;
                })
            }
        });
        Vue.component('test-jerry', {
            data: function () {
                return {
                    num: 0
                }
            },
            template: `
               <div>
                    <div>JERRY:{{num}}</div>
                    <div>
                        <button @click='handle'>點選</button>
                    </div>
               </div>
            `,
            methods: {
                handle: function () {
                    //觸發兄弟元件的事件
                    hub.$emit('tom-event', 1)

                }
            },
            mounted: function () {
                //監聽事件
                //val是兄弟元件傳遞過來的
                hub.$on('jerry-event', (val) => {
                    this.num += val;
                })
            }
        });
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件中的內容',
            },
            methods: {
                handle: function () {
                    hub.$off('tom-event');
                    hub.$off('jerry-event');
                }
            }
        })
    </script>

輸出:

父元件
銷燬
TOM:3
點選
JERRY:4
點選
元件插槽

元件插槽的作用

  • 父元件向子元件傳遞內容(模板內容)

在这里插入图片描述

元件插槽基本使用
<div id="app">
        <alert-box>有bug發生</alert-box>
        <alert-box>有一個警告</alert-box>
        <alert-box></alert-box>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('alert-box', {
            template: `
                <div>
                    <strong>ERROR:</strong>
                    <slot>預設內容</slot>
                </div>
            `
        })
        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {

            }
        })
    </script>

輸出:

ERROR: 有bug發生
ERROR: 有一個警告
ERROR: 預設內容
具名插槽用法

用法一:

 <div id="app">
        <base-layout>
            <p slot="header">標題資訊</p>
            <p>主要內容1</p>
            <p>主要內容2</p>
            <p slot="footer">底部資訊</p>
        </base-layout>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('base-layout', {
            template: `
               <div>
                    <header>
                        <slot name="header"></slot>
                    </header>
                    <main>
                        <slot></slot>
                    </main>
                    <footer>
                        <slot name="footer"></slot>
                    </footer>
               </div>
            
            `
        })
        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {

            }
        })
    </script>

輸出:

標題資訊

主要內容1

主要內容2

底部資訊

結構程式碼:

在这里插入图片描述

用法二:

 <div id="app">
        <base-layout>
            <template slot="header">
                <p>標題資訊1</p>
                <p>標題資訊2</p>
            </template>
            <p>主要內容1</p>
            <p>主要內容2</p>
            <template slot="footer">
                <p>底部資訊1</p>
                <p>底部資訊2</p>
            </template>
        </base-layout>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('base-layout', {
            template: `
               <div>
                    <header>
                        <slot name="header"></slot>
                    </header>
                    <main>
                        <slot></slot>
                    </main>
                    <footer>
                        <slot name="footer"></slot>
                    </footer>
               </div>
            
            `
        })
        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {

            }
        })
    </script>

輸出:

標題資訊1

標題資訊2

主要內容1

主要內容2

底部資訊1

底部資訊2

結構程式碼:

在这里插入图片描述

作用域插槽

應用場景:父元件對子元件的內容進行加工處理

<style type="text/css">
        .current{
            color: red;
        }
 </style>
 <div id="app">
        <fruit-list :list="list">
            <template slot-scope="slotProps">
                <strong v-if="slotProps.info.id==3" class="current">{{slotProps.info.name}}</strong>
                <span v-else>{{slotProps.info.name}}</span>
            </template>
        </fruit-list>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('fruit-list', {
            props: ['list'],
            template: `
               <div>
                    <ul>
                        <li :key='item.id' v-for='item in list'>
                            <slot :info='item'>{{item.name}}</slot>
                        </li>
                    </ul>
               </div>
            
            `
        })
        var vm = new Vue({
            el: '#app',
            data: {
                list: [{
                    id: 1,
                    name: 'apple'
                }, {
                    id: 2,
                    name: 'orange'
                }, {
                    id: 3,
                    name: 'banana'
                }]
            },
            methods: {

            }
        })
    </script>

輸出:

在这里插入图片描述

前後端互動模式

介面呼叫方式
  • 原生ajax
  • 基於jQuery的ajax
  • fetch
  • axios
URL地址格式

1.傳統形式的URL

  • schema://host:port/path?query#fragment
  1. schema:協定。例如http、https、ftp等
  2. host:域名或者IP地址
  3. port:埠,http預設埠是80,可以省略
  4. path:路徑,例如/abc/a/b/c
  5. query:查詢參數,例如uname=zhangsan&age=12
  6. fragment:錨點(雜湊Hash),用於定位頁面的某個位置

2.Resful形式的URL

  • HTTP請求方式
  1. GET 查詢
  2. POST 新增
  3. PUT 修改
  4. DELETE 刪除

Promise用法

  • 非同步呼叫效果分析
  1. 定時任務
  2. Ajax
  3. 事件函數
  • 多次非同步呼叫的依賴分析
  1. 多次非同步呼叫的結果順序不確定
  2. 非同步呼叫結果如果存在依賴需要巢狀
Promise概述

promise是非同步程式設計的一種解決方案,從語法上講,Promise是一個物件,它可以獲取非同步操作的訊息

使用Promise主要有以下好處:

  • 可以避免多層非同步呼叫巢狀問題(回撥地獄)
  • Promise物件提供了簡潔的API,使得控制非同步操作更加容易
Promise基本用法
  • 範例化Promise物件,建構函式中傳遞函數,該函數中用於處理非同步任務
  • resolve和reject兩個參數用於處理呈貢與是白的兩種情況,並通過p.then獲取處理結果
<script type="text/javascript">
        var p = new Promise(function (resolve, reject) {
            //這裏用於實現非同步任務
            setTimeout(function () {
                var flag = false;
                if (flag) {
                    //正常情況
                    resolve('hello');
                } else {
                    //異常情況
                    reject('出錯了');
                }
            }, 1000);
        })
        p.then(function (data) {
            console.log(data);//hello
        }, function (info) {
            console.log(info);//出錯了

        })
    </script>
Promise常用的API

1.實體方法

  • p.then() 得到非同步任務的正確結果
  • p.catch() 獲取異常資訊
  • p.finally() 成功與否都會執行(尚且不是正式標準)
function foo() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    resolve(123);
                    // reject('出錯了');
                }, 100)
            })
        }
        // 方法一
        // foo()
        //     .then(function (data) {
        //         console.log(data);
        //     })
        //     .catch(function (data) {
        //         console.log(data);

        //     })
        //     .finally(function () {
        //         console.log('finished');

        //     })
        // -----------------------------------
        // 方法二
        foo()
        .then(function(data){
            console.log(data);       
        },function(data){
            console.log(data);
        })
        .finally(function(){
            console.log('finished');
            
        })
    </script>

2.物件方法

  • Promise.all() 併發處理多個非同步任務,所有任務都執行完成才能 纔能得到結果
  • Promise.race() 併發處理多個非同步任務,只要有一個任務完成就能得到結果

axios用法

axios的基本特性

axios是一個基於Promise用於瀏覽器和node.js的http用戶端

它具有以下特徵:

  1. 支援瀏覽器和node.js
  2. 支援promise
  3. 能攔截請求和響應
  4. 自動轉換JSON數據
axios基本用法
axios.get('http://localhost:3000/data').then(function (ret) {
            //    data是固定的用法,用於獲取後臺的實際數據
            console.log(ret.data);

        })
axios的常用API
  • get 查詢數據

GET傳遞參數

在这里插入图片描述

  • post 新增數據

POST傳遞參數
在这里插入图片描述
在这里插入图片描述

  • put 修改數據

put傳遞參數

在这里插入图片描述

  • delete 刪除數據

DELETE傳遞參數

在这里插入图片描述

axios的響應結果

響應結果的主要屬性

  • data:實際響應回來的數據
  • headers:響應頭資訊
  • status:響應狀態碼
  • statusText:響應狀態資訊
axios的全域性設定

在这里插入图片描述

axios攔截器
1.請求攔截器

在这里插入图片描述

2.響應攔截器

响应拦截器.png

async/await的基本用法

在这里插入图片描述

async/await處理多個非同步請求

在这里插入图片描述