Vue 核心技術

来源:https://www.cnblogs.com/codechen8848/archive/2022/10/19/16808083.html
-Advertisement-
Play Games

本文主要記錄學習 Vue.js 的核心技術,涵蓋常用指令、計算屬性、監聽屬性、數據監測原理、生命周期鉤子等。 ...


1.1 Vue簡介

1.1.1 官網

1.1.2 介紹與描述

  1. 動態構建用戶界面的 漸進式 JavaScript 框架
  2. 作者:尤雨溪

1.1.3 Vue的特點

  • 遵循 MVVM 模式
  • 編碼簡潔,體積小,運行效率高,適合移動/PC端開發
  • 它本身只關註UI,也可以引入其它第三方庫開發項目

1.1.4 與其它JS框架的關聯

  1. 借鑒 Angular模板和數據綁定技術
  2. 借鑒 React組件化和虛擬 DOM 技術

1.1.5 Vue 周邊庫

  1. Vue CLI: 項目腳手架
  2. Vue Resource
  3. Axios
  4. Vue Router: 路由
  5. Vuex: 狀態管理
  6. element-ui:基於 VueUI 組件庫(PC端)
    ......

1.2 初識 Vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>初識Vue</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        初識Vue:
            1.想讓 Vue工作,就必須創建一個 Vue實例,且要傳入一個配置對象;
            2.root 容器里的代碼依然符合 html 規範,只不過混入了一些特殊的 Vue語法;
            3.root 容器里的代碼被稱為【Vue模板】;
            4.Vue 實例和容器是一一對應的;
            5.真實開發中只有一個 Vue 實例,並且會配合著組件一起使用;
            6.{{xxx}} 中的 xxx 要寫 js 表達式,且 xxx 可以自動讀取到 data 中的所有屬性;
            7.一旦 data 中的數據發生改變,那麼頁面中用到該數據的地方也會自動更新;

            註意區分:js 表達式和 js 代碼(語句)
                1.表達式:一個表達式會產生一個值,可以放在任何一個需要值的地方:
                    (1). a
                    (2). a+b
                    (3). demo(1)
                    (4). x === y ? 'a' : 'b'

                2.js代碼(語句)
                    (1). if(){}
                    (2). for(){}
    -->
    <div id="root">
        <h1>Hello {{name}}</h1>
    </div>

    <script>
        // 阻止 Vue 在啟動時生成生產提示
        // You are running Vue in development mode.
        // Make sure to turn on production mode when deploying for production.
        // See more tips at https://vuejs.org/guide/deployment.html
        Vue.config.productionTip = false

        // 創建 Vue 實例
        new Vue({
            // el 用於指定當前 Vue 實例為哪個容器服務,值通常為 css 選擇器字元串
            el: '#root', 
            // data 用於存儲數據,數據供 el 所指定的容器去使用
            data: {
                name: "張三"
            },
        })
    </script>
</body>
</html>

1.3 模板語法

1.3.1 模板的理解

html 中包含了一些 js 語法代碼,語法分為兩種,分別為:

  1. 插值語法(雙大括弧表達式)
  2. 指令(以v-開頭)

1.3.2 插值語法

  1. 功能:用於解析標簽體內容

1.3.3 指令語法

  1. 功能:解析標簽屬性、解析標簽體內容、綁定事件
  2. 舉例:v-bind:href='xxxx'xxxx 會作為 js 表達式被解析
  3. 說明:Vue 中有有很多的指令,此處只是用 v-bind 舉個例子

1.3.4 示例代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 模板語法</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        Vue模板語法有2大類:
            1.插值語法:
                功能:用於解析標簽體內容。
                寫法:{{xxx}},xxx 是 js 表達式,且可以直接讀取到 data 中的所有屬性。
            2.指令語法:
                功能:用於解析標簽(包括:標簽屬性、標簽體內容、綁定事件.....)。
                舉例:v-bind:href="xxx" 或  簡寫為 :href="xxx",xxx同樣要寫js表達式,且可以直接讀取到 data 中的所有屬性。
                備註:Vue 中有很多的指令,且形式都是:v-????,此處我們只是拿 v-bind 舉個例子。
    -->
    <div id="root">
        <h1>插值語法</h1>
        <h3>你好,{{name}}</h3>
        <hr></hr>
        <h1>指令語法</h1>
        <a href="http://baidu.com">去百度</a>
        <br/>
        <a v-bind:href="school.url">去百度</a>
        <br/>
        <a :href="school.url">去百度</a>
    </div>

    <script>
        // 阻止 Vue 在啟動時生成生產提示
        Vue.config.productionTip = false

        new Vue({
            el: "#root",
            data: {
                name: "張三",
                school: {
                    url: "http://baidu.com"
                }
            }
        })
    </script>
</body>
</html>

1.4 數據綁定

1.4.1 單向數據綁定

  1. 語法:v-bind:href="xxx" 或簡寫為 :href
  2. 特點:數據只能從 data 流向頁面

1.4.2 雙向數據綁定

  1. 語法:v-model:value="xxx" 或簡寫為 v-model="xxx"
  2. 特點:數據不僅能從 data 流向頁面,還能從頁面流向 data

1.4.3 示例代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>數據綁定</title>
    <script src="../js/vue.js"></script>
</head>
<body>

    <!--  Vue中有2種數據綁定的方式:
            1.單向綁定(v-bind):數據只能從 data 流向頁面。
            2.雙向綁定(v-model):數據不僅能從 data 流向頁面,還可以從頁面流向 data 。
                備註:
                    1.雙向綁定一般都應用在表單類元素上(如:input、select等)
                    2.v-model:value 可以簡寫為 v-model,因為 v-model預設收集的就是 value 值。
    -->
    <div id="root">
        <!-- 單向綁定 -->

        <!-- 普通寫法 -->
        單向綁定普通寫法:<input type="text" v-bind:value="name"></input>
        <br/>
        <!-- 簡寫 -->
        單向綁定簡寫:<input type="text" :value="name"></input>
        
        <hr></hr>
        <!-- 雙向綁定 -->
        <!-- 普通寫法 -->
        雙向綁定普通寫法:<input type="text" v-model:value="name"></input>
        <br/>
        <!-- 簡寫 -->
        雙向綁定簡寫:<input type="text" v-model="name"></input>

        <!-- 如下代碼是錯誤的,因為 v-model只能應用在表單類元素(輸入類元素)上 -->
        <!-- <h2 v-model="name">: v-model is not supported on this element type. 
            If you are working with contenteditable, it's recommended to wrap a library dedicated for that purpose inside a custom component. -->
        <h2 v-model:x="name"></h2>
        


    </div>

    <script>
        // 組織 Vue 在啟動時生成生產提示
        Vue.config.productionTip = false

        new Vue({
            el: "#root",
            data: {
                name: "張三"
            }
        })
    </script>
</body>
</html>

1.5 MVVM模型

  1. M:模型(Model):對應 data 中的數據
  2. V:視圖(View):模板
  3. VM:視圖模型(ViewModel):Vue 實例對象

image-20220810144417339

1.6 事件處理

1.6.1 綁定監聽

  1. v-on:xxx="fun"
  2. @xxx="fun"
  3. @xxx="fun(參數)"
  4. 預設事件形參:event
  5. 隱含屬性對象:$event
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件的基本使用</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        事件的基本使用:
            1.使用 v-on:xxx 或 @xxx 綁定事件,其中 xxx 是事件名;
            2.事件的回調需要配置在 vue 實例中的 methods 對象,最終會在 vm 實例上;
            3.methods 中配置配置的函數,不要用箭頭函數,否則 this 就不是 vm 實例了;
            4.methods 中配置的函數,都是被 vue 實例所管理的函數,this 的指向是 vm 或 組件實例對象;
            5.@click="demo" 和 @click="demo($event)" 效果一致,但後者可以傳參
     -->
    <div id="root">
        <h2>歡迎來到 {{name}} 學習</h2>
        <button v-on:click = "showInfo01">點我去學習1</button>
        <button v-on:click = "showInfo02">點我去學習2</button>
        <button @click = "showInfo03">點我去學習3</button>
        <button @click = "showInfo04(88)">點我去學習4</button>
        <button @click = "showInfo05(88, $event)">點我去學習5</button>
    </div>
    
    <script>
        // 阻止 vue 在啟動時生成生產提示
        Vue.config.productionTip = false

        new Vue({
            el: "#root",
            data() {
                return {
                    name: "北京大學"
                }
            },
            
            methods: {
                showInfo01() {
                    alert("點我去學習1")
                },
                
                showInfo02(event) {
                    console.log(event);
                },

                showInfo03() {
                    alert("點我去學習3")
                },

                showInfo04(number) {
                    console.log(number);
                    alert("點我去學習4" + number)
                },

                showInfo05(number, event) {
                    console.log(number, event);
                    alert("點我去學習5")
                },
            },
        })
    </script>
</body>
</html>

1.6.2 事件修飾符

  1. prevent: 阻止事件的預設行為 event.preventDefault()
  2. stop: 停止事件冒泡 event.stopPropagation()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件修飾符</title>
    <script src="../js/vue.js"></script>
    <style>
        *{
            margin-top: 20px;
        }
        .box1 {
            height: 50px;
            padding: 5px;
            background-color: skyblue;
        }
        .box2 {
            height: 50px;
            padding: 5px;
            background-color: orange;
        }
        .box3 {
            height: 5px;
            padding: 5px;
            background-color: rebeccapurple;
        }
        .box4 {
            height: 50px;
            padding: 5px;
            background-color: antiquewhite;
        }
        .list {
            width: 200px;
            height: 200px;
            background-color: peru;
            /* 在容器內生成滑動視窗 */
            overflow: auto;
        }
        li {
            height: 100px;
        }
    </style>
</head>
<body>
    <!-- 
        Vue中的事件修飾符:
            1.prevent:阻止預設事件(常用);
            2.stop:阻止事件冒泡(常用);
            3.once:事件只觸發一次(常用);
            4.capture:使用事件的捕獲模式;
            5.self:只有event.target是當前操作的元素時才觸發事件;
            6.passive:事件的預設行為立即執行,無需等待事件回調執行完畢;
    -->

    <div id="root">
        <!-- 1.阻止預設事件 -->
        <!-- 彈窗點擊確認後會跳轉到百度 -->
        <a href="https://www.baidu.com" @click="gotoBaidu">點我去百度</a><br/>
        <!-- 彈窗點擊確認後不會跳轉到百度 -->
        <a href="https://www.baidu.com" @click.prevent="gotoBaidu">點我去百度</a><br>

        <!-- 2.stop:阻止事件冒泡 -->
        <div class = "box1" @click="showInfo">
            <button @click="showInfo">點我提示信息</button>
        </div>
        <div class = "box1" @click="showInfo">
            <button @click.stop="showInfo">點我提示信息</button>
        </div>
        
        <!--  3.once:事件只觸發一次 -->
        <button @click.once="showInfo">點我提示信息</button>

        <!-- 4.capture:使用事件的捕獲模式 -->
        <div class="box2" @click.capture="showMessage(1)">
            div01
            <div class="box3" @click.capture="showMessage(2)">
                div02
            </div>
        </div>

        <!-- 5.self:只有event.target是當前操作的元素時才觸發事件 -->
        <div class="box4" @click.self="showInfo">
            <button @click="showInfo">點我提示信息</button>
        </div>

        <!--  6.passive:事件的預設行為立即執行,無需等待事件回調執行完畢 -->\
        <!--  
            @scroll、@wheel 滾輪滑動事件,兩者的區別:
                1.scroll是頁面滾動條滾動會觸發的事件,而 wheel是滑鼠滾輪滾動會觸發的事件。
                2,一旦滾動條到底部後,滑動滑鼠滾輪繼續滾動,wheel 就會一直觸發,而 scroll 不會觸發
        -->

        <ul class="list" @scroll="list">
        <!-- <ul class="list" @wheel="list"> -->
        <!-- <ul class="list" @wheel.passive="list"> -->
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>

        <!-- 7.多個修飾符 -->
        <div @click="showInfo">
            <a href="https://www.baidu.com" @click="showInfo">點我去百度</a>
            <a href="https://www.baidu.com" @click.prevent.stop="showInfo">點我去百度</a>
        </div>

    </div>

    <script>
        // 阻止 vue 在啟動時生成生產提示
        Vue.config.productionTip = false

        new Vue({
            el: "#root",
            data: {

            },
            methods: {
                gotoBaidu() {
                    alert("點我去百度!")
                },
                showInfo() {
                    alert("hello world")
                },
                showMessage(message) {
                    console.log(message);
                },
                list() {
                    for(let i = 0; i < 10; i++) {
                        console.log("#");
                    }
                    console.log("累壞了");
                }
            },
        })
    </script>
</body>
</html>

1.6.3 按鍵修飾符

  1. keycode: 操作的是某個 keycode 值的鍵
  2. keyName: 操作的某個按鍵名的鍵(少部分)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>鍵盤事件</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        1.Vue中常用的按鍵別名:
            回車 => enter
            刪除 => delete (捕獲“刪除”和“退格”鍵)
            退出 => esc
            空格 => space
            換行 => tab (特殊,必須配合keydown去使用)
            上 => up
            下 => down
            左 => left
            右 => right

        2.Vue未提供別名的按鍵,可以使用按鍵原始的key值去綁定,但註意要轉為kebab-case(短橫線命名)

        3.系統修飾鍵(用法特殊):ctrl、alt、shift、meta
            (1).配合keyup使用:按下修飾鍵的同時,再按下其他鍵,隨後釋放其他鍵,事件才被觸發。
            (2).配合keydown使用:正常觸發事件。

        4.也可以使用keyCode去指定具體的按鍵(不推薦)

        5.Vue.config.keyCodes.自定義鍵名 = 鍵碼,可以去定製按鍵別名
    -->
    <div id="root">
        <h3>歡迎來到{{name}}學習</h3>
        <!-- @keydown、@keyup兩者的區別:前者是鍵盤按下事件,後者是鍵盤恢復事件 -->
        <input placeholder="回車事件" @keydown="demo" ></input><br/>
        <input placeholder="回車事件" @keydown.enter="demo"></input><br/>
        <input placeholder="回車事件" @keydown.13="demo"></input><br/>
        <input placeholder="回車事件" @keydown.huiche="demo"></input><br/>

        <input placeholder="刪除事件" @keydown.delete="demo"></input><br/>
        <input placeholder="退出事件" @keydown.esc="demo"></input><br/>
        <input placeholder="空格事件" @keydown.space="demo"></input><br/>
        <input placeholder="換行事件" @keydown.tab="demo"></input><br/>
        <input placeholder="上事件" @keydown.up="demo"></input><br/>
        <input placeholder="下事件" @keydown.down="demo"></input><br/>
        <input placeholder="左事件" @keydown.left="demo"></input><br/>
        <input placeholder="右事件" @keydown.right="demo"></input><br/>
    </div>

    <script>
        // 阻止 vue 在啟動時生成生產提示
        Vue.config.productionTip = false
        // 自定義鍵盤別名
        Vue.config.keyCodes.huiche = 13

        new Vue({
            el: "#root",
            data: {
                name: "Blili"
            },
            methods: {
                demo(event) {
                    // 輸出鍵值
                    console.log(event.key, event.keyCode);
                    console.log("hello world");
                }
            },
        })
    </script>
</body>
</html>

1.7 計算屬性與監視屬性

1.7.1 計算屬性 computed

  1. 要顯示的數據不存在,要通過計算得來。

  2. computed 對象中定義計算屬性。

  3. 在頁面中使用插值語法來顯示計算的結果。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>姓名案例-計算屬性實現</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            計算屬性:
                1.定義:要用的屬性不存在,要通過已有屬性計算得來。
                2.原理:底層藉助了 Objcet.defineproperty 方法提供的 getter 和 setter 。
                3.get 函數什麼時候執行?
                    (1).初次讀取時會執行一次。
                    (2).當依賴的數據發生改變時會被再次調用。
                4.優勢:與 methods 實現相比,內部有緩存機制(復用),效率更高,調試方便。
                5.備註:
                    1.計算屬性最終會出現在 vm 上,直接讀取使用即可。
                    2.如果計算屬性要被修改,那必須寫 set 函數去響應修改,且 set 中要引起計算時依賴的數據發生改變。
         -->
        <div id="root">
            姓:<input type="text" v-model="firstName"> <br/>
            名:<input type="text" v-model="lastName"> <br/>
            <!-- 測試:<input type="text" v-model="x"> <br/> -->
            全名:<span>{{fullName}}</span> <br/>
            <!-- 全名:<span>{{fullName}}</span> <br/>
            全名:<span>{{fullName}}</span> <br/>
            全名:<span>{{fullName}}</span> -->
    
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            const vm = new Vue({
                el: "#root",
                data: {
                    firstName: "張",
                    lastName: "三",
                },
                computed: {
                    fullName: {
                        get() {
                            //get 有什麼作用?當有人讀取 fullName 時,get 就會被調用,且返回值就作為 fullName 的值
    					    //get 什麼時候調用?1.初次讀取 fullName 時。2.所依賴的數據發生變化時。
                            console.log("get 被調用了");
                            return this.firstName + " - " + this.lastName
                        },
                        // set 什麼時候被調用?fullName 被修改時
                        set(value) {
                            console.log("set 被調用了");
                            const arr = value.split("-")
                            this.firstName = arr[0]
                            this.lastName = arr[1]
                        }
                    }
                }
            });
        </script>
    </body>
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>姓名案例-計算屬性簡寫</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            姓:<input type="text" v-model="firstName"> <br/>
            名:<input type="text" v-model="lastName"> <br/>
            <!-- 測試:<input type="text" v-model="x"> <br/> -->
            全名:<span>{{fullName}}</span> <br/>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    firstName: "張",
                    lastName: "三",
                },
                computed: {
                    // fullName:function() {
                    //     return this.firstName + " - " + this.lastName
                    // },
                    fullName() {
                        return this.firstName + " - " + this.lastName
                    }
                }
            })
        </script>
    </body>
    </html>
    

1.7.2 監視屬性 watch

  1. 通過通過 vm 對象的 $watch()watch 配置來監視指定的屬性

  2. 當屬性變化時,回調函數自動調用,在函數內部進行計算

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>天氣案例-監視屬性</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            監視屬性 watch:
                1.當被監視的屬性變化時, 回調函數自動調用, 進行相關操作
                2.監視的屬性必須存在,才能進行監視!!
                3.監視的兩種寫法:
                    (1).new Vue 時傳入 watch 配置
                    (2).通過 vm.$watch 監視
         -->
        <div id="root">
            <h2>今天天氣很{{info}}</h2>
            <button @click="changeWeather">切換天氣</button>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            const vm = new Vue({
                el: "#root",
                data: {
                    isHot: true
                },
                computed: {
                    info() {
                        return this.isHot ? "炎熱":"涼爽";
                    }
                },
                methods: {
                    changeWeather() {
                        this.isHot = !this.isHot
                    }
                },
                watch: {
                    // isHot: {
                    //     // 初始化的時候讓 handler 調用一下
                    //     immediate: true,
                    //     // handler 什麼時候被調用?當isHot值發生變化時
                    //     handler(newValue, oldValue) {
                    //         console.log("isHot 值被修改了", newValue, oldValue);
                    //     }
                    // },
                    
                    // computed 中定義的屬性也能被監視
                    info: {
                        handler(newValue, oldValue) {
                            console.log("info值被修改了", newValue, oldValue);
                        }
                    }
                }
            });
    
            // watch 屬性的另外一種寫法
            vm.$watch("isHot", {
                // 初始化的時候讓 handler 調用一下
                immediate: true,
                // handler 什麼時候被調用?當isHot值發生變化時
                handler(newValue, oldValue) {
                    console.log("isHot 值被修改了", newValue, oldValue);
                }
            })
        </script>
    </body>
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>天氣案例-深度監視</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            深度監視:
                (1).Vue 中的 watch 預設不監測對象內部值的改變(一層)。
                (2).配置 deep:true 可以監測對象內部值改變(多層)。
                備註:
                    (1).Vue 自身可以監測對象內部值的改變,但 Vue 提供的 watch 預設不可以!
                    (2).使用 watch 時根據數據的具體結構,決定是否採用深度監視。
    
         -->
        <div id="root">
            <h2>今天天氣很{{info}}</h2>
            <button @click="changeWeather">切換天氣</button>
            <hr/>
            <h3>x的值是:{{numbers.x}}</h3>
            <button @click="numbers.x ++">點我讓x + 1</button>
            <h3>y的值是:{{numbers.y}}</h3>
            <button @click="numbers.y ++">點我讓y + 1</button>
            <br/>
            <br/>
            <button @click="numbers = {x:666, y:888}">徹底替換掉numbers</button>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    isHot: true,
                    numbers: {
                        x: 100,
                        y: 200
                    },
                    a: {
                        b: {
                            c: {
                                d: "e"
                            }
                        }
                    }
                },
                computed: {
                    info() {
                        return this.isHot ? "炎熱":"涼爽";
                    }
                },
                methods: {
                    changeWeather() {
                        this.isHot = !this.isHot
                    }
                },
                watch: {
                    isHot: {
                        // 初始化的時候讓 handler 調用一下
                        immediate: true,
                        // handler 什麼時候被調用?當isHot值發生變化時
                        handler(newValue, oldValue) {
                            console.log("isHot 值被修改了", newValue, oldValue);
                        }
                    },
                    
                    // computed 中定義的屬性也能被監視
                    info: {
                        handler(newValue, oldValue) {
                            console.log("info值被修改了", newValue, oldValue);
                        }
                    },
                    // 監視多級結構中某個屬性的變化
                    "numbers.x": {
                        handler(newValue, oldValue) {
                            console.log("numbers.x 值被修改了", newValue, oldValue);
                        }
                    },
                    //監視多級結構中所有屬性的變化
                    numbers: {
                        deep: true,
                        handler(newValue, oldValue) {
                            console.log("numbers 值被修改了", newValue, oldValue);
                        }
                    }
                }
            })
        </script>
    </body>
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>天氣案例-監視屬性-簡寫</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>今天天氣很{{info}}</h2>
            <button @click="changeWeather">切換天氣</button>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            const vm = new Vue({
                el: "#root",
                data: {
                    isHot: true
                },
                computed: {
                    info() {
                        return this.isHot ? "炎熱":"涼爽"
                    }
                },
                methods: {
                    changeWeather() {
                        this.isHot = !this.isHot
                    }
                },
                watch: {
                    // 正常寫法
                    // isHot: {
                    //     // 在初始化時調用 handler 一次
                    //     immediate: true,
                    //     handler(newValue, oldValue) {
                    //         console.log("isHot 值被修改了", newValue, oldValue);
                    //     }
                    // },
    
                    // 簡寫
                    // 簡寫的缺點時不能寫屬性信息
                    // isHot(newValue, oldValue) {
                    //     console.log("isHot 值被修改了", newValue, oldValue);
                    // }
                },
            });
    
            // 正常寫法
            // vm.$watch("isHot", {
            //     // 初始化的時候讓 handler 調用一下
            //     immediate: true,
            //     // handler 什麼時候被調用?當isHot值發生變化時
            //     handler(newValue, oldValue) {
            //         console.log("isHot 值被修改了", newValue, oldValue);
            //     }
            // })
            // 簡寫
            vm.$watch("isHot", function(newValue, oldValue) {
                console.log("isHot 值被修改了", newValue, oldValue);
            })
        </script>
    </body>
    </html>
    

1.8 classstyle 綁定

1.8.1 理解

  1. 在應用界面中,某個(些)元素的樣式是變化的
  2. class/style 綁定就是專門用來實現動態樣式效果的技術

1.8.2 class 綁定

  1. :class='xxx'
  2. 表達式是字元串:'classA'
  3. 表達式是對象:{classA:isA,classB:isB}
  4. 表達式是數組:['classA','classB']

1.8.3 style 綁定

  1. :style="{color:activeColor,fontSize:fontSize+'px'}"
  2. 其中 activeColor/fontSizedata 屬性

1.8.4 示例代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>綁定樣式</title>
    <style>
        .basic{
            width: 400px;
            height: 100px;
            border: 1px solid black;
        }
        
        .happy{
            border: 4px solid red;;
            background-color: rgba(255, 255, 0, 0.644);
            background: linear-gradient(30deg,yellow,pink,orange,yellow);
        }
        .sad{
            border: 4px dashed rgb(2, 197, 2);
            background-color: gray;
        }
        .normal{
            background-color: skyblue;
        }

        .box1{
            background-color: yellowgreen;
        }
        .box2{
            font-size: 30px;
            text-shadow:2px 2px 10px red;
        }
        .box3{
            border-radius: 20px;
        }
    </style>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        綁定樣式:
            1. class樣式
                寫法:class="xxx" xxx可以是字元串、對象、數組。
                    字元串寫法適用於:類名不確定,要動態獲取。
                    對象寫法適用於:要綁定多個樣式,個數不確定,名字也不確定。
                    數組寫法適用於:要綁定多個樣式,個數確定,名字也確定,但不確定用不用。
            2. style樣式
                :style="{fontSize: xxx}"其中xxx是動態值。
                :style="[a,b]"其中a、b是樣式對象。
            3. 二者的區別:
                :class 動態綁定 class 的名稱,然後專門在 <style></style> 中去設置對應 class 的樣式
                :style 動態綁定 style 的效果,直接把 css 寫在裡面

     -->
    <div id="root">

        <!-- 綁定 class 樣式(字元串寫法),適用於:樣式的類名不確定,需要動態指定 -->
        <div class="basic" :class="mood" @click="changeMood1">{{name}}</div> </br>

        <!-- 綁定 class 樣式(數組寫法),適用於:要綁定的樣式個數不確定、名字也不確定-->
        <div class="basic" :class="moodArr">{{name}}</div> </br>

        <!-- 綁定 class 樣式(對象寫法),適用於:要綁定的樣式個數確定、名字也確定,但要動態決定用不用 -->
        <div class="basic" :class="moodObj">{{name}}</div> </br>
        
        <!-- 綁定 style 樣式(對象寫法) -->
        <div class="basic" :style="{fontSize: '40px', color: 'orange'}">{{name}}</div> </br>
        <div class="basic" :style="styleObj">{{name}}</div> </br>

        <!-- 綁定 style 樣式(數組寫法) -->
        <div class="basic" :style="styleArr">{{name}}</div> </br>


    </div>

    <script>
        // 阻止 vue 在啟動時生成生產提示
        Vue.config.productionTip = false

        new Vue({
            el: "#root",
            data: {
                name: "Hello World",
                mood: "happy",
                moodArr: ["box1", "box2", "box3"],
                moodObj: {
                    box1: true,
                    box2: false,
                    box3: true
                },
                styleObj: {
                    fontSize: "40px",
                    color: "red"
                },
                styleArr: [
                    {
                        fontSize: "40px",
                        color: "blue"
                    },
                    {
                        backgroundColor: "green"
                    }
                ]
            },
            methods: {
                changeMood1() {
                    this.mood = "sad"
                },
            },
        })
    </script>
</body>
</html>

1.9 條件渲染

1.9.1 條件渲染指令

  1. v-ifv-else
  2. v-show

1.9.2 比較 v-ifv-show

  1. 如果需要頻繁切換 v-show 較好
  2. 當條件不成立時,v-if 的所有子節點不會解析(項目中使用)

1.9.3 示例代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>條件渲染</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        條件渲染:
            1.v-if
                寫法:
                        (1).v-if="表達式" 
                        (2).v-else-if="表達式"
                        (3).v-else="表達式"
                適用於:切換頻率較低的場景。
                特點:不展示的 DOM 元素直接被移除。
                註意:v-if 可以和: v-else-if、v-else 一起使用,但要求結構不能被“打斷”。

            2.v-show
                寫法:v-show="表達式"
                適用於:切換頻率較高的場景。
                特點:不展示的 DOM 元素未被移除,僅僅是使用樣式隱藏掉
                
            3.備註:使用 v-if 時,元素可能無法獲取到,而使用 v-show 一定可以獲取到。

    -->
    <div id="root">
        <!-- 使用 v-show 來做條件渲染 -->
        <!-- <h2 style="display: none;"> 歡迎來到百度</h2> -->
        <h2 v-show="false"> 歡迎來到{{name}}</h2>
        <h2 v-show=" 1 === 1"> 歡迎來到{{name}}</h2>
        
        <!-- 使用 v-if 來做條件渲染 -->
        <h2 v-if="false"> 歡迎來到{{name}}</h2>
        <h2 v-if="2 === 2"> 歡迎來到{{name}}</h2>

        <!-- v-if與template的配合使用 -->
        <template v-if="n === 1">
            <h2>Angular</h2>
            <h2>React</h2>
            <h2>Vue</h2>
        </template>


    </div>

    <script>
        // 阻止 vue 在啟動時生成生產提示
        Vue.config.productionTip = false

        new Vue({
            el: "#root",
            data: {
                name: "百度",
                n: 1
            }
        })
    </script>
</body>
</html>

1.10 列表渲染

1.10.1 列表顯示指令

  1. 遍曆數組:v-for/index
  2. 遍歷對象:v-for/key

1.10.2 示例代碼

  1. 基本列表

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>基本列表</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            v-for指令:
                1.用於展示列表數據
                2.語法:v-for="(item, index) in xxx" :key="yyy"
                3.可遍歷:數組、對象、字元串(用的很少)、指定次數(用的很少)
        -->
        <div id="root">
            <!-- 遍曆數組 -->
            <h2>遍曆數組</h2>
            <!-- 用 id 作為 key -->
            <!-- <ul v-for="p in personList" :key = "p.id">
                <li>{{p.name}} - {{p.age}}</li>
            </ul> -->
            <!-- 用索引 index 作為 key -->
            <ul v-for="(p, index) in personList" :key = "index">
                <li>{{p.name}} - {{p.age}}</li>
            </ul>
            <hr/>
            
            <!-- 遍歷對象 -->
            <h2>遍歷對象</h2>
            <!-- 註意:key 在後面,value 在前面 -->
            <ul v-for="(v, k) in car" ::key="k">
                <li>{{k}} - {{v}}</li>
            </ul>
            <hr/>
            
            <!-- 遍歷字元串 -->
            <h2>遍歷字元串</h2>
            <ul v-for="(char, index) in str" :key="index">
                <ul>{{index}} - {{char}}</ul>
            </ul>
            <hr/>
    
            <!-- 遍歷指定次數 -->
            <h2>遍歷指定次數</h2>
            <ul v-for="i in 5">
                <ul>{{i}}</ul>
            </ul>
    
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    personList: [
                        {id: "001", name: "張三", age: 18},
                        {id: "002", name: "李四", age: 19},
                        {id: "003", name: "王五", age: 20},
                    ],
                    car: {
                        name: "奧迪 A8",
                        price: "80萬",
                        color: "黑色"
                    },
                    str: "hello world"
                }
            })
        </script>
    </body>
    </html>
    
  2. key 的原理

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>key的原理</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            面試題:react、vue 中的 key 有什麼作用?(key 的內部原理)
                1. 虛擬 DOM 中 key 的作用:
                    key 是虛擬 DOM 對象的標識,當數據發生變化時,Vue 會根據【新數據】生成【新的虛擬 DOM】, 
                    隨後 Vue 進行【新虛擬 DOM】與【舊虛擬 DOM】的差異比較,比較規則如下:
                2.對比規則:
                    (1).舊虛擬 DOM 中找到了與新虛擬 DOM 相同的 key:
                        ①.若虛擬 DOM 中內容沒變, 直接使用之前的真實 DOM!
                        ②.若虛擬 DOM 中內容變了, 則生成新的真實 DOM,隨後替換掉頁面中之前的真實 DOM。
                    (2).舊虛擬 DOM 中未找到與新虛擬 DOM 相同的 key
                        創建新的真實DOM,隨後渲染到到頁面。
                3. 用 index 作為 key 可能會引發的問題:
                    1. 若對數據進行:逆序添加、逆序刪除等破壞順序操作:
                                    會產生沒有必要的真實 DOM 更新 ==> 界面效果沒問題, 但效率低。
                    2. 如果結構中還包含輸入類的 DOM:
                                    會產生錯誤 DOM 更新 ==> 界面有問題。
                4. 開發中如何選擇 key?:
                    1.最好使用每條數據的唯一標識作為 key, 比如 id、手機號、身份證號、學號等唯一值。
                    2.如果不存在對數據的逆序添加、逆序刪除等破壞順序操作,僅用於渲染列表用於展示,
                        使用 index 作為 key 是沒有問題的。
        -->
        <div id="root">
            <h2>遍曆數組</h2>
            <button @click="add">在前面添加一個趙六</button>
            <!-- <ul v-for="(p, index) in personList" :key = "p.id"> -->
            <ul v-for="(p, index) in personList" :key = "index">
                <li>
                    {{p.name}} - {{p.age}}
                    <input type="text"></input>
                </li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    personList: [
                        {id: "001", name: "張三", age: 18},
                        {id: "002", name: "李四", age: 19},
                        {id: "003", name: "王五", age: 20},
                    ],
                },
                methods: {
                    add() {
                        this.personList.unshift({
                            id: "004", name: "趙六", age: 38
                        })
                    }
                },
            })
        </script>
    </body>
    </html>
    
  3. 列表過濾

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>列表過濾</title></title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>遍曆數組</h2>
            <input type="text" placeholder="輸入名字進行過濾" v-model="keyWord"></input>
            <ul v-for="(p, index) in filterPersonList" ::key="index">
                <li>{{p.name}} - {{p.age}} - {{p.sex}}</li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    keyWord:'',
                    personList:[
                        {id:'001',name:'馬冬梅',age:19,sex:'女'},
                        {id:'002',name:'周冬雨',age:20,sex:'女'},
                        {id:'003',name:'周傑倫',age:21,sex:'男'},
                        {id:'004',name:'溫兆倫',age:22,sex:'男'}
                    ],
                    filterPersonList: []
                },
                // 用 comouted 實現
                computed: {
                    // filterPersonList() {
                    //     return this.personList.filter((item) => {
                    //         return item.name.indexOf(this.keyWord) > -1
                    //     })
                    // }
                },
                // 用 watch 實現
                watch: {
                    keyWord: {
                        immediate: true,
                        handler(val) {
                            this.filterPersonList = this.personList.filter((item) => {
                                return item.name.indexOf(this.keyWord) > -1
                            })
                        }
                    }
                }
            })
        </script>
    </body>
    </html>
    
  4. 列表排序

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>列表排序</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>遍曆數組</h2>
            <input type="text" placeholder="輸入名字進行過濾" v-model="keyWord"></input>
            <button @click="sortType = 1">升序排序</button></button>
            <button @click="sortType = 2">降序排列</button></button>
            <button @click="sortType = 0">原序排序</button></button>
            <ul v-for="(p, index) in filterPersonList" ::key="index">
                <li>{{p.name}} - {{p.age}} - {{p.sex}}</li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    keyWord:'',
                    personList:[
                        {id:'001',name:'馬冬梅',age:19,sex:'女'},
                        {id:'002',name:'周冬雨',age:20,sex:'女'},
                        {id:'003',name:'周傑倫',age:21,sex:'男'},
                        {id:'004',name:'溫兆倫',age:22,sex:'男'}
                    ],
                    sortType: 1
                },
                 // 用 comouted 實現
                computed: {
                    filterPersonList() {
                        const arr = this.personList.filter((item) => {
                            return item.name.indexOf(this.keyWord) > -1
                        })
                        if (this.sortType) {
                            arr.sort((p1, p2) => {
                                return this.sortType === 1 ? p1.age - p2.age : p2.age - p1.age
                            })
                        }
                        return arr
                    }
                },
            })
        </script>
    </body>
    </html>
    
  5. 更新時的一個問題

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>更新時的一個問題</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>人員列表</h2>
            <button @click="updateMa">更新馬冬梅的信息</button>
            <ul>
                <li v-for="p in personList" :key="p.id">
                    {{p.name}} - {{p.age}} - {{p.sex}}
                </li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    personList: [
                        {id:'001',name:'馬冬梅',age:19,sex:'女'},
                        {id:'002',name:'周冬雨',age:20,sex:'女'},
                        {id:'003',name:'周傑倫',age:21,sex:'男'},
                        {id:'004',name:'溫兆倫',age:22,sex:'男'}
                    ]
                },
                methods: {
                    updateMa() {
                        // 奏效的寫法
                        // this.personList[0].name = "馬老師"
                        // this.personList[0].age = 50
                        // this.personList[0].sex = "男"
    
                        // 不奏效的寫法
                        this.personList[0] = {name: "馬老師", age: 50, sex: "男"}
                    }
                },
            })
        </script>
    </body>
    </html>
    
  6. Vue 監測數據改變的原理-對象

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vue 數據檢測改變的原理-對象</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>學校名稱: {{name}}</h2>
            <h2>學校地址: {{address}}</h2>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    name: "北京大學",
                    address: "北京",
                    student: {
                        name: "tom",
                        age: {
                            rAge: 40,
                            sAge: 18
                        },
                        friends: [
                            {name: "jack", age: 38}
                        ]
                    }
                }
            })
        </script>
    </body>
    </html>
    
  7. 模擬一個數據監測

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>模擬一個數據檢測</title>
    </head>
    <body>
        <div id="root">
    
        </div>
        <script>
            let data = {
                name: "北京大學",
                address: "北京",
                student: {
                    name: "tom",
                    age: 18
                }
            }
    
            // 創建一個監視的實例對象,用於監視 data 中屬性的變化
            const obs = new Observer(data);
    
            // 準備一個 vm 實例對象
            let vm = {}
            vm._data = data = obs
    
            function Observer(obj) {
                // 彙總對象中所有的屬性形成一個數組
                const keys = Object.keys(obj);
    
                // 遍歷
                keys.forEach((k) => {
                    Object.defineProperty(this, k, {
                        get() {
                            return obj[k]
                        },
                        set(val) {
                            obj[k] = val;
                        }
                    })
                })
            }
            // 存在的問題是對於深層次的屬性無法生成 get set 如:student 中的屬性
        </script>
    </body>
    </html>
    
  8. Vue.set 的使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vue.set的使用</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h1>學校信息</h1>
            <h2>學校名稱:{{shcool.name}}</h2>
            <h2>學校地址:{{shcool.address}}</h2>
            <hr/>
            <h1>學生信息</h1>
            <button @click="addSex">添加性別</button>
            <h2>學生姓名:{{student.name}}</h2>
            <h2>學生年齡:真實-{{student.age.rAge}} 對外-{{student.age.sAge}}</h2>
            <h2 v-if="student.sex">學生性別:{{student.sex}}</h2>
            <h2>學生朋友</h2>
            <ul>
                <li v-for="(f, index) in student.friends" :key="index">
                    {{f.name}} - {{f.age}}
                </li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    shcool: {
                        name: "北京大學",
                        address: "北京"
                    },
                    student: {
                        name: "tom",
                        age: {
                            rAge: 40,
                            sAge: 18
                        },
                        friends: [
                            {name: "jerry", age: 35},
                            {name: "tony", age: 36}
                        ]
                    }
                },
                methods: {
                    addSex() {
                        // 寫法一
                        // Vue.set(this.student, 'sex', "男")
                        // 寫法二
                        this.$set(this.student, 'sex', "女")
                    }
                },
            })
        </script>
    </body>
    </html>
    
  9. Vue 監測數據改變的原理-數組

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vue監測數據改變的原理-數組</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h1>學校信息</h1>
            <h2>學校名稱:{{school.name}}</h2>
            <h2>學校地址:{{school.address}}</h2>
            <h2>校長是:{{school.leader}}</h2>
            <hr/>
            <h1>學生信息</h1>
            <button @click="addHobby">在最前面添加一個愛好</button>
            <button @click="updateHobby">修改第一個愛好</button>
            <h2>姓名:{{student.name}}</h2>
            <h2 v-if="student.sex">性別:{{student.sex}}</h2>
            <h2>年齡:真實{{student.age.rAge}},對外{{student.age.sAge}}</h2>
            <h2>愛好</h2>
            <ul>
                <li v-for="(h,index) in student.hobby" :key="index">
                    {{h}}
                </li>
            </ul>
            <h2>朋友們</h2>
            <ul>
                <li v-for="(f,index) in student.friends" :key="index">
                    {{f.name}}--{{f.age}}
                </li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    school:{
    					name: "北京大學",
    					address: "北京",
    				},
    				student:{
    					name: "tom",
    					age:{
    						rAge: 40,
    						sAge: 29,
    					},
    					hobby: ["抽煙", "喝酒", "燙頭"],
    					friends: [
    						{ name: "jerry", age: 35},
    						{ name: "tony", age: 36}
    					]
    				}
                },
                methods: {
                    addHobby() {
                        this.student.hobby.unshift("睡覺")
                    },
                    updateHobby() {
                        // 不起作用
                        // this.student.hobby[0] = "唱跳"
                        
                        // 方式一
                        // Vue.set(this.student.hobby, 0, '唱跳')
    
                        // 方式二
                        // this.$set(this.student.hobby, 0, "唱跳")
    
                        // 方式三
                        this.student.hobby.splice(0, 1, "唱跳")
    
                    }
                },
            })
        </script>
    </body>
    </html>
    
  10. 總結 Vue 的數據監測

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>總結Vue中的數據監測</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            Vue監視數據的原理:
                1. Vue會監視 data 中所有層次的數據。
    
                2. 如何監測對象中的數據?
                    通過 setter 實現監視,且要在 new Vue 時就傳入要監測的數據。
                    (1).對象中後追加的屬性,Vue 預設不做響應式處理
                    (2).如需給後添加的屬性做響應式,請使用如下API:
                        Vue.set(target,propertyName/index,value) 或 
                        vm.$set(target,propertyName/index,value)
    
                3. 如何監測數組中的數據?
                    通過包裹數組更新元素的方法實現,本質就是做了兩件事:
                        (1).調用原生對應的方法對數組進行更新。
                        (2).重新解析模板,進而更新頁面。
    
                4.在 Vue 修改數組中的某個元素一定要用如下方法:
                    1.使用這些 API: push()、pop()、shift()、unshift()、splice()、sort()、reverse()
                    2.Vue.set() 或 vm.$set()
                特別註意:Vue.set() 和 vm.$set() 不能給 vm 或 vm的根數據對象 添加屬性!!!
        -->
        <div id="root">
            <h1>學生信息</h1>
            <button @click="addSex">添加性別</button> <br/>
            <button @click="updateSex">修改性別</button> <br/>
            <button @click="addFriend">在列表首位添加一個朋友</button> <br/>
            <button @click="updateFirstFriendName">修改第一個朋友的名字為:趙六</button> <br/>
            <button @click="addHobby">添加一個愛好</button> <br/>
            <button @click="updateHobby">修改第一個愛好為:籃球</button> <br/>
            <button @click="removeRap">過濾掉愛好中的rap</button> <br/>
            <h2>姓名: {{ student.name }}</h2>
            <h2>年齡: {{ student.age }}</h2>
            <h2 v-if="student.sex">性別: {{ student.sex }}</h2>
            <h2>愛好: </h2>
            <ul>
                <li v-for="(h, index) in student.hobby" :key="index">
                    {{ h }}
                </li>
            </ul>
            <h2>朋友: </h2>
            <ul>
        
    
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 自動化管理軟體與Ansible安裝 常見的自動化管理軟體 常見的自動化管理軟體有哪些? Linux中,常見的配置管理工具有 puppet saltstack ansible Puppet puppet是什麼 puppet是一種Linux/Unix平臺下的集中配置管理系統,使用自有的puppet描述語 ...
  • 前言 有些Windows客戶端因主板電池沒電或其他原因,每次啟動系統後,讀取到BIOS的時間是初始時間(1970年)或錯誤的時間,這時需要系統啟動後立即向時間伺服器同步一次時間。 該方法是添加一個Windows任務計劃,讓系統啟動後立即向時間伺服器同步時間,所以不需要藉助任何插件。 環境 Windo ...
  • nginx配置文件,rewrite,if rewrit 語法:rewrite regex replacement flag; 比如 rewrite ^/images/(.*\.jpg)$ /imgs/$1 break; 又如 rewrite ^/bbs/(.*)$ http://www.idfsof ...
  • 定義:select語句中嵌套select語句,被嵌套的select語句是子查詢。 子查詢可以出現在: select ....(select).. from ....(select).. where ....(select).. 1.where後面嵌套子查詢 select * from emp whe ...
  • 摘要:本文將通過一句口訣,教你如何辨別索引失效。 本文分享自華為雲社區《虛竹哥教你一句口訣辨別索引失效七大場景》,作者:小虛竹 。 一、口訣 教你一句功法口訣:模 型 數 或 運 最 快 二、初始化數據 創建存儲引擎為InnoDB的學生表 drop table if exists student; ...
  • 說起大數據中的應用,很多同學可能馬上會想起用戶畫像。 用戶畫像,英文稱之為User Profile,通過用戶畫像可以完美地抽象出一個用戶的信息全貌,通過用戶畫像數據可以精準地分析用戶的各種行為習慣,如消費習慣、興趣愛好、能力情況等等重要用戶信息。 通常用戶畫像是通過給用戶建標簽系統來實現的,本文介紹... ...
  • GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。 GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。 本文來源:社區原創投稿;作者:王慶勛。 客戶的一些應用系統使用的JDK1.7版本,在將資料庫遷移到MySQL8.0的過程中,發現有些MySQL conn ...
  • 作為游戲類App的用戶運營,難免會遇到以下問題: 競品競爭激烈,新用戶獲取成本很高,該如何有效輓回卸載用戶和沉默用戶? 預算有限,該對哪些人群做活動才能獲得較高的ROI呢? 如何根據用戶屬性和用戶行為劃分用戶價值層級,並精準觸達呢? 如今,高昂的買量成本讓游戲的吸量越發艱難,存量用戶的精細化運營成為 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...