Vue 核心技術(shù)

1.1 Vue簡介

1.1.1 官網(wǎng)

1.1.2 介紹與描述

  1. 動態(tài)構(gòu)建用戶界面的 漸進式 JavaScript 框架
  2. 作者:尤雨溪

1.1.3 Vue的特點

  • 遵循 MVVM 模式
  • 編碼簡潔养盗,體積小除嘹,運行效率高埠况,適合移動/PC端開發(fā)
  • 它本身只關(guān)注UI枉长,也可以引入其它第三方庫開發(fā)項目

1.1.4 與其它JS框架的關(guān)聯(lián)

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

1.1.5 Vue 周邊庫

  1. Vue CLI: 項目腳手架

  2. Vue Resource

  3. Axios

  4. Vue Router: 路由

  5. Vuex: 狀態(tài)管理

  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工作壳影,就必須創(chuàng)建一個 Vue實例,且要傳入一個配置對象抽减;
            2.root 容器里的代碼依然符合 html 規(guī)范郁竟,只不過混入了一些特殊的 Vue語法;
            3.root 容器里的代碼被稱為【Vue模板】狡逢;
            4.Vue 實例和容器是一一對應(yīng)的宁舰;
            5.真實開發(fā)中只有一個 Vue 實例,并且會配合著組件一起使用奢浑;
            6.{{xxx}} 中的 xxx 要寫 js 表達式蛮艰,且 xxx 可以自動讀取到 data 中的所有屬性;
            7.一旦 data 中的數(shù)據(jù)發(fā)生改變雀彼,那么頁面中用到該數(shù)據(jù)的地方也會自動更新印荔;

            注意區(qū)分:js 表達式和 js 代碼(語句)
                1.表達式:一個表達式會產(chǎn)生一個值,可以放在任何一個需要值的地方:
                    (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 在啟動時生成生產(chǎn)提示
        // 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

        // 創(chuàng)建 Vue 實例
        new Vue({
            // el 用于指定當(dāng)前 Vue 實例為哪個容器服務(wù)详羡,值通常為 css 選擇器字符串
            el: '#root', 
            // data 用于存儲數(shù)據(jù)仍律,數(shù)據(jù)供 el 所指定的容器去使用
            data: {
                name: "張三"
            },
        })
    </script>
</body>
</html>

1.3 模板語法

1.3.1 模板的理解

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

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

1.3.2 插值語法

  1. 功能:用于解析標(biāo)簽體內(nèi)容

1.3.3 指令語法

  1. 功能:解析標(biāo)簽屬性水泉、解析標(biāo)簽體內(nèi)容、綁定事件
  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.插值語法:
                功能:用于解析標(biāo)簽體內(nèi)容。
                寫法:{{xxx}}蟹漓,xxx 是 js 表達式炕横,且可以直接讀取到 data 中的所有屬性。
            2.指令語法:
                功能:用于解析標(biāo)簽(包括:標(biāo)簽屬性葡粒、標(biāo)簽體內(nèi)容份殿、綁定事件.....)。
                舉例: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 >去百度</a>
        <br/>
        <a v-bind:href="school.url">去百度</a>
        <br/>
        <a :href="school.url">去百度</a>
    </div>

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

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

1.4 數(shù)據(jù)綁定

1.4.1 單向數(shù)據(jù)綁定

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

1.4.2 雙向數(shù)據(jù)綁定

  1. 語法:v-model:value="xxx" 或簡寫為 v-model="xxx"
  2. 特點:數(shù)據(jù)不僅能從 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>數(shù)據(jù)綁定</title>
    <script src="../js/vue.js"></script>
</head>
<body>

    <!--  Vue中有2種數(shù)據(jù)綁定的方式:
            1.單向綁定(v-bind):數(shù)據(jù)只能從 data 流向頁面司蔬。
            2.雙向綁定(v-model):數(shù)據(jù)不僅能從 data 流向頁面,還可以從頁面流向 data 姨蝴。
                備注:
                    1.雙向綁定一般都應(yīng)用在表單類元素上(如: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只能應(yīng)用在表單類元素(輸入類元素)上 -->
        <!-- <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 在啟動時生成生產(chǎn)提示
        Vue.config.productionTip = false

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

1.5 MVVM模型

  1. M:模型(Model):對應(yīng) data 中的數(shù)據(jù)
  2. V:視圖(View):模板
  3. VM:視圖模型(ViewModel):Vue 實例對象
image-20220810144417339.png

1.6 事件處理

1.6.1 綁定監(jiān)聽

  1. v-on:xxx="fun"
  2. @xxx="fun"
  3. @xxx="fun(參數(shù))"
  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.事件的回調(diào)需要配置在 vue 實例中的 methods 對象,最終會在 vm 實例上泉手;
            3.methods 中配置配置的函數(shù)黔寇,不要用箭頭函數(shù),否則 this 就不是 vm 實例了斩萌;
            4.methods 中配置的函數(shù)缝裤,都是被 vue 實例所管理的函數(shù),this 的指向是 vm 或 組件實例對象颊郎;
            5.@click="demo" 和 @click="demo($event)" 效果一致憋飞,但后者可以傳參
     -->
    <div id="root">
        <h2>歡迎來到 {{name}} 學(xué)習(xí)</h2>
        <button v-on:click = "showInfo01">點我去學(xué)習(xí)1</button>
        <button v-on:click = "showInfo02">點我去學(xué)習(xí)2</button>
        <button @click = "showInfo03">點我去學(xué)習(xí)3</button>
        <button @click = "showInfo04(88)">點我去學(xué)習(xí)4</button>
        <button @click = "showInfo05(88, $event)">點我去學(xué)習(xí)5</button>
    </div>
    
    <script>
        // 阻止 vue 在啟動時生成生產(chǎn)提示
        Vue.config.productionTip = false

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

                showInfo03() {
                    alert("點我去學(xué)習(xí)3")
                },

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

                showInfo05(number, event) {
                    console.log(number, event);
                    alert("點我去學(xué)習(xí)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;
            /* 在容器內(nèi)生成滑動窗口 */
            overflow: auto;
        }
        li {
            height: 100px;
        }
    </style>
</head>
<body>
    <!-- 
        Vue中的事件修飾符:
            1.prevent:阻止默認事件(常用);
            2.stop:阻止事件冒泡(常用)姆吭;
            3.once:事件只觸發(fā)一次(常用)榛做;
            4.capture:使用事件的捕獲模式;
            5.self:只有event.target是當(dāng)前操作的元素時才觸發(fā)事件内狸;
            6.passive:事件的默認行為立即執(zhí)行检眯,無需等待事件回調(diào)執(zhí)行完畢;
    -->

    <div id="root">
        <!-- 1.阻止默認事件 -->
        <!-- 彈窗點擊確認后會跳轉(zhuǎn)到百度 -->
        <a  @click="gotoBaidu">點我去百度</a><br/>
        <!-- 彈窗點擊確認后不會跳轉(zhuǎn)到百度 -->
        <a  @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:事件只觸發(fā)一次 -->
        <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是當(dāng)前操作的元素時才觸發(fā)事件 -->
        <div class="box4" @click.self="showInfo">
            <button @click="showInfo">點我提示信息</button>
        </div>

        <!--  6.passive:事件的默認行為立即執(zhí)行昆淡,無需等待事件回調(diào)執(zhí)行完畢 -->\
        <!--  
            @scroll锰瘸、@wheel 滾輪滑動事件,兩者的區(qū)別:
                1.scroll是頁面滾動條滾動會觸發(fā)的事件昂灵,而 wheel是鼠標(biāo)滾輪滾動會觸發(fā)的事件避凝。
                2,一旦滾動條到底部后眨补,滑動鼠標(biāo)滾輪繼續(xù)滾動恕曲,wheel 就會一直觸發(fā),而 scroll 不會觸發(fā)
        -->

        <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  @click="showInfo">點我去百度</a>
            <a  @click.prevent.stop="showInfo">點我去百度</a>
        </div>

    </div>

    <script>
        // 阻止 vue 在啟動時生成生產(chǎn)提示
        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值去綁定,但注意要轉(zhuǎn)為kebab-case(短橫線命名)

        3.系統(tǒng)修飾鍵(用法特殊):ctrl实蓬、alt茸俭、shift吊履、meta
            (1).配合keyup使用:按下修飾鍵的同時,再按下其他鍵调鬓,隨后釋放其他鍵艇炎,事件才被觸發(fā)。
            (2).配合keydown使用:正常觸發(fā)事件腾窝。

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

        5.Vue.config.keyCodes.自定義鍵名 = 鍵碼缀踪,可以去定制按鍵別名
    -->
    <div id="root">
        <h3>歡迎來到{{name}}學(xué)習(xí)</h3>
        <!-- @keydown、@keyup兩者的區(qū)別:前者是鍵盤按下事件虹脯,后者是鍵盤恢復(fù)事件 -->
        <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 在啟動時生成生產(chǎn)提示
        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 計算屬性與監(jiān)視屬性

1.7.1 計算屬性 computed

  1. 要顯示的數(shù)據(jù)不存在驴娃,要通過計算得來。

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

  3. 在頁面中使用插值語法來顯示計算的結(jié)果唇敞。

    <!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>姓名案例-計算屬性實現(xiàn)</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            計算屬性:
                1.定義:要用的屬性不存在跟磨,要通過已有屬性計算得來玷坠。
                2.原理:底層借助了 Objcet.defineproperty 方法提供的 getter 和 setter 。
                3.get 函數(shù)什么時候執(zhí)行密末?
                    (1).初次讀取時會執(zhí)行一次镶柱。
                    (2).當(dāng)依賴的數(shù)據(jù)發(fā)生改變時會被再次調(diào)用旷档。
                4.優(yōu)勢:與 methods 實現(xiàn)相比,內(nèi)部有緩存機制(復(fù)用)歇拆,效率更高彬犯,調(diào)試方便。
                5.備注:
                    1.計算屬性最終會出現(xiàn)在 vm 上查吊,直接讀取使用即可谐区。
                    2.如果計算屬性要被修改,那必須寫 set 函數(shù)去響應(yīng)修改逻卖,且 set 中要引起計算時依賴的數(shù)據(jù)發(fā)生改變宋列。
         -->
        <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 在啟動時生成生產(chǎn)提示
            Vue.config.productionTip = false
    
            const vm = new Vue({
                el: "#root",
                data: {
                    firstName: "張",
                    lastName: "三",
                },
                computed: {
                    fullName: {
                        get() {
                            //get 有什么作用?當(dāng)有人讀取 fullName 時评也,get 就會被調(diào)用炼杖,且返回值就作為 fullName 的值
                         //get 什么時候調(diào)用?1.初次讀取 fullName 時盗迟。2.所依賴的數(shù)據(jù)發(fā)生變化時坤邪。
                            console.log("get 被調(diào)用了");
                            return this.firstName + " - " + this.lastName
                        },
                        // set 什么時候被調(diào)用?fullName 被修改時
                        set(value) {
                            console.log("set 被調(diào)用了");
                            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 在啟動時生成生產(chǎn)提示
            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 監(jiān)視屬性 watch

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

  2. 當(dāng)屬性變化時罚缕,回調(diào)函數(shù)自動調(diào)用艇纺,在函數(shù)內(nèi)部進行計算

    <!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>天氣案例-監(jiān)視屬性</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            監(jiān)視屬性 watch:
                1.當(dāng)被監(jiān)視的屬性變化時, 回調(diào)函數(shù)自動調(diào)用, 進行相關(guān)操作
                2.監(jiān)視的屬性必須存在,才能進行監(jiān)視!黔衡!
                3.監(jiān)視的兩種寫法:
                    (1).new Vue 時傳入 watch 配置
                    (2).通過 vm.$watch 監(jiān)視
         -->
        <div id="root">
            <h2>今天天氣很{{info}}</h2>
            <button @click="changeWeather">切換天氣</button>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產(chǎn)提示
            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 調(diào)用一下
                    //     immediate: true,
                    //     // handler 什么時候被調(diào)用蚓聘?當(dāng)isHot值發(fā)生變化時
                    //     handler(newValue, oldValue) {
                    //         console.log("isHot 值被修改了", newValue, oldValue);
                    //     }
                    // },
                    
                    // computed 中定義的屬性也能被監(jiān)視
                    info: {
                        handler(newValue, oldValue) {
                            console.log("info值被修改了", newValue, oldValue);
                        }
                    }
                }
            });
    
            // watch 屬性的另外一種寫法
            vm.$watch("isHot", {
                // 初始化的時候讓 handler 調(diào)用一下
                immediate: true,
                // handler 什么時候被調(diào)用?當(dāng)isHot值發(fā)生變化時
                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>天氣案例-深度監(jiān)視</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            深度監(jiān)視:
                (1).Vue 中的 watch 默認不監(jiān)測對象內(nèi)部值的改變(一層)盟劫。
                (2).配置 deep:true 可以監(jiān)測對象內(nèi)部值改變(多層)夜牡。
                備注:
                    (1).Vue 自身可以監(jiān)測對象內(nèi)部值的改變,但 Vue 提供的 watch 默認不可以侣签!
                    (2).使用 watch 時根據(jù)數(shù)據(jù)的具體結(jié)構(gòu)塘装,決定是否采用深度監(jiān)視。
    
         -->
        <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 在啟動時生成生產(chǎn)提示
            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 調(diào)用一下
                        immediate: true,
                        // handler 什么時候被調(diào)用影所?當(dāng)isHot值發(fā)生變化時
                        handler(newValue, oldValue) {
                            console.log("isHot 值被修改了", newValue, oldValue);
                        }
                    },
                    
                    // computed 中定義的屬性也能被監(jiān)視
                    info: {
                        handler(newValue, oldValue) {
                            console.log("info值被修改了", newValue, oldValue);
                        }
                    },
                    // 監(jiān)視多級結(jié)構(gòu)中某個屬性的變化
                    "numbers.x": {
                        handler(newValue, oldValue) {
                            console.log("numbers.x 值被修改了", newValue, oldValue);
                        }
                    },
                    //監(jiān)視多級結(jié)構(gòu)中所有屬性的變化
                    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>天氣案例-監(jiān)視屬性-簡寫</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>今天天氣很{{info}}</h2>
            <button @click="changeWeather">切換天氣</button>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產(chǎn)提示
            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: {
                    //     // 在初始化時調(diào)用 handler 一次
                    //     immediate: true,
                    //     handler(newValue, oldValue) {
                    //         console.log("isHot 值被修改了", newValue, oldValue);
                    //     }
                    // },
    
                    // 簡寫
                    // 簡寫的缺點時不能寫屬性信息
                    // isHot(newValue, oldValue) {
                    //     console.log("isHot 值被修改了", newValue, oldValue);
                    // }
                },
            });
    
            // 正常寫法
            // vm.$watch("isHot", {
            //     // 初始化的時候讓 handler 調(diào)用一下
            //     immediate: true,
            //     // handler 什么時候被調(diào)用蹦肴?當(dāng)isHot值發(fā)生變化時
            //     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. 在應(yīng)用界面中,某個(些)元素的樣式是變化的
  2. class/style 綁定就是專門用來實現(xiàn)動態(tài)樣式效果的技術(shù)

1.8.2 class 綁定

  1. :class='xxx'
  2. 表達式是字符串:'classA'
  3. 表達式是對象:{classA:isA,classB:isB}
  4. 表達式是數(shù)組:['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可以是字符串型檀、對象、數(shù)組听盖。
                    字符串寫法適用于:類名不確定胀溺,要動態(tài)獲取。
                    對象寫法適用于:要綁定多個樣式皆看,個數(shù)不確定仓坞,名字也不確定。
                    數(shù)組寫法適用于:要綁定多個樣式腰吟,個數(shù)確定无埃,名字也確定,但不確定用不用毛雇。
            2. style樣式
                :style="{fontSize: xxx}"其中xxx是動態(tài)值嫉称。
                :style="[a,b]"其中a、b是樣式對象灵疮。
            3. 二者的區(qū)別:
                :class 動態(tài)綁定 class 的名稱织阅,然后專門在 <style></style> 中去設(shè)置對應(yīng) class 的樣式
                :style 動態(tài)綁定 style 的效果,直接把 css 寫在里面

     -->
    <div id="root">

        <!-- 綁定 class 樣式(字符串寫法)震捣,適用于:樣式的類名不確定荔棉,需要動態(tài)指定 -->
        <div class="basic" :class="mood" @click="changeMood1">{{name}}</div> </br>

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

        <!-- 綁定 class 樣式(對象寫法)润樱,適用于:要綁定的樣式個數(shù)確定、名字也確定羡棵,但要動態(tài)決定用不用 -->
        <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 樣式(數(shù)組寫法) -->
        <div class="basic" :style="styleArr">{{name}}</div> </br>


    </div>

    <script>
        // 阻止 vue 在啟動時生成生產(chǎn)提示
        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. 當(dāng)條件不成立時壹若,v-if 的所有子節(jié)點不會解析(項目中使用)

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 一起使用啊犬,但要求結(jié)構(gòu)不能被“打斷”。

            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 在啟動時生成生產(chǎn)提示
        Vue.config.productionTip = false

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

1.10 列表渲染

1.10.1 列表顯示指令

  1. 遍歷數(shù)組: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.用于展示列表數(shù)據(jù)
                2.語法:v-for="(item, index) in xxx" :key="yyy"
                3.可遍歷:數(shù)組、對象席怪、字符串(用的很少)应闯、指定次數(shù)(用的很少)
        -->
        <div id="root">
            <!-- 遍歷數(shù)組 -->
            <h2>遍歷數(shù)組</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/>
    
            <!-- 遍歷指定次數(shù) -->
            <h2>遍歷指定次數(shù)</h2>
            <ul v-for="i in 5">
                <ul>{{i}}</ul>
            </ul>
    
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產(chǎn)提示
            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 的內(nèi)部原理)
                1. 虛擬 DOM 中 key 的作用:
                    key 是虛擬 DOM 對象的標(biāo)識,當(dāng)數(shù)據(jù)發(fā)生變化時刻撒,Vue 會根據(jù)【新數(shù)據(jù)】生成【新的虛擬 DOM】, 
                    隨后 Vue 進行【新虛擬 DOM】與【舊虛擬 DOM】的差異比較骨田,比較規(guī)則如下:
                2.對比規(guī)則:
                    (1).舊虛擬 DOM 中找到了與新虛擬 DOM 相同的 key:
                        ①.若虛擬 DOM 中內(nèi)容沒變, 直接使用之前的真實 DOM!
                        ②.若虛擬 DOM 中內(nèi)容變了, 則生成新的真實 DOM声怔,隨后替換掉頁面中之前的真實 DOM态贤。
                    (2).舊虛擬 DOM 中未找到與新虛擬 DOM 相同的 key
                        創(chuàng)建新的真實DOM,隨后渲染到到頁面醋火。
                3. 用 index 作為 key 可能會引發(fā)的問題:
                    1. 若對數(shù)據(jù)進行:逆序添加悠汽、逆序刪除等破壞順序操作:
                                    會產(chǎn)生沒有必要的真實 DOM 更新 ==> 界面效果沒問題, 但效率低。
                    2. 如果結(jié)構(gòu)中還包含輸入類的 DOM:
                                    會產(chǎn)生錯誤 DOM 更新 ==> 界面有問題芥驳。
                4. 開發(fā)中如何選擇 key?:
                    1.最好使用每條數(shù)據(jù)的唯一標(biāo)識作為 key, 比如 id柿冲、手機號、身份證號兆旬、學(xué)號等唯一值姻采。
                    2.如果不存在對數(shù)據(jù)的逆序添加、逆序刪除等破壞順序操作爵憎,僅用于渲染列表用于展示慨亲,
                        使用 index 作為 key 是沒有問題的。
        -->
        <div id="root">
            <h2>遍歷數(shù)組</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 在啟動時生成生產(chǎn)提示
            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>遍歷數(shù)組</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 在啟動時生成生產(chǎn)提示
            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 實現(xiàn)
                computed: {
                    // filterPersonList() {
                    //     return this.personList.filter((item) => {
                    //         return item.name.indexOf(this.keyWord) > -1
                    //     })
                    // }
                },
                // 用 watch 實現(xiàn)
                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>遍歷數(shù)組</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 在啟動時生成生產(chǎn)提示
            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 實現(xiàn)
                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 在啟動時生成生產(chǎn)提示
            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 監(jiān)測數(shù)據(jù)改變的原理-對象

    <!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 數(shù)據(jù)檢測改變的原理-對象</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h2>學(xué)校名稱: {{name}}</h2>
            <h2>學(xué)校地址: {{address}}</h2>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產(chǎn)提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    name: "北京大學(xué)",
                    address: "北京",
                    student: {
                        name: "tom",
                        age: {
                            rAge: 40,
                            sAge: 18
                        },
                        friends: [
                            {name: "jack", age: 38}
                        ]
                    }
                }
            })
        </script>
    </body>
    </html>
    
  7. 模擬一個數(shù)據(jù)監(jiān)測

    <!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>模擬一個數(shù)據(jù)檢測</title>
    </head>
    <body>
        <div id="root">
    
        </div>
        <script>
            let data = {
                name: "北京大學(xué)",
                address: "北京",
                student: {
                    name: "tom",
                    age: 18
                }
            }
    
            // 創(chuàng)建一個監(jiān)視的實例對象宝鼓,用于監(jiān)視 data 中屬性的變化
            const obs = new Observer(data);
    
            // 準(zhǔn)備一個 vm 實例對象
            let vm = {}
            vm._data = data = obs
    
            function Observer(obj) {
                // 匯總對象中所有的屬性形成一個數(shù)組
                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>學(xué)校信息</h1>
            <h2>學(xué)校名稱:{{shcool.name}}</h2>
            <h2>學(xué)校地址:{{shcool.address}}</h2>
            <hr/>
            <h1>學(xué)生信息</h1>
            <button @click="addSex">添加性別</button>
            <h2>學(xué)生姓名:{{student.name}}</h2>
            <h2>學(xué)生年齡:真實-{{student.age.rAge}} 對外-{{student.age.sAge}}</h2>
            <h2 v-if="student.sex">學(xué)生性別:{{student.sex}}</h2>
            <h2>學(xué)生朋友</h2>
            <ul>
                <li v-for="(f, index) in student.friends" :key="index">
                    {{f.name}} - {{f.age}}
                </li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產(chǎn)提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    shcool: {
                        name: "北京大學(xué)",
                        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 監(jiān)測數(shù)據(jù)改變的原理-數(shù)組

    <!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監(jiān)測數(shù)據(jù)改變的原理-數(shù)組</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="root">
            <h1>學(xué)校信息</h1>
            <h2>學(xué)校名稱:{{school.name}}</h2>
            <h2>學(xué)校地址:{{school.address}}</h2>
            <h2>校長是:{{school.leader}}</h2>
            <hr/>
            <h1>學(xué)生信息</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 在啟動時生成生產(chǎn)提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    school:{
                     name: "北京大學(xué)",
                     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. 總結(jié) Vue 的數(shù)據(jù)監(jiān)測

    <!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>總結(jié)Vue中的數(shù)據(jù)監(jiān)測</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 
            Vue監(jiān)視數(shù)據(jù)的原理:
                1. Vue會監(jiān)視 data 中所有層次的數(shù)據(jù)。
    
                2. 如何監(jiān)測對象中的數(shù)據(jù)愚铡?
                    通過 setter 實現(xiàn)監(jiān)視蛉签,且要在 new Vue 時就傳入要監(jiān)測的數(shù)據(jù)胡陪。
                    (1).對象中后追加的屬性,Vue 默認不做響應(yīng)式處理
                    (2).如需給后添加的屬性做響應(yīng)式碍舍,請使用如下API:
                        Vue.set(target柠座,propertyName/index,value) 或 
                        vm.$set(target片橡,propertyName/index妈经,value)
    
                3. 如何監(jiān)測數(shù)組中的數(shù)據(jù)?
                    通過包裹數(shù)組更新元素的方法實現(xiàn)捧书,本質(zhì)就是做了兩件事:
                        (1).調(diào)用原生對應(yīng)的方法對數(shù)組進行更新吹泡。
                        (2).重新解析模板,進而更新頁面经瓷。
    
                4.在 Vue 修改數(shù)組中的某個元素一定要用如下方法:
                    1.使用這些 API: push()爆哑、pop()、shift()舆吮、unshift()揭朝、splice()、sort()色冀、reverse()
                    2.Vue.set() 或 vm.$set()
                特別注意:Vue.set() 和 vm.$set() 不能給 vm 或 vm的根數(shù)據(jù)對象 添加屬性L陡ぁ!呐伞!
        -->
        <div id="root">
            <h1>學(xué)生信息</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>
                <li v-for="(f, index) in student.friends" :key="index">
                    {{ f.name }} - {{f.age}}
                </li>
            </ul>
        </div>
    
        <script>
            // 阻止 vue 在啟動時生成生產(chǎn)提示
            Vue.config.productionTip = false
    
            new Vue({
                el: "#root",
                data: {
                    student: {
                        name: "張三",
                        age: 18,
                        hobby: ["唱", "跳", "rap"],
                        friends: [
                            { name: "李四", age: 20},
                            { name: "王五", age: 19},
                        ]
                    }
                },
                methods: {
                    addSex() {
                        // 不起作用
                        // this.student.sex = "男"
    
                        // 方式一
                        // Vue.set(this.student, "sex", "男")
    
                        // 方式二
                        this.$set(this.student, "sex", "男")
                    },
                    updateSex() {
                        this.student.sex = "女"
                    },
                    addFriend() {
                        this.student.friends.unshift({ name: "老王", age: 28})
                    },
                    updateFirstFriendName() {
                        this.student.friends[0].name = "趙六"
                    },
                    addHobby() {
                        this.student.hobby.push("籃球")
                    },
                    updateHobby() {
                        // 不起作用
                        // this.student.hobby[0] = "籃球"
    
                        // 方式一
                        // Vue.set(this.student.hobby, 0, "籃球")
    
                        // 方式二
                        // this.$set(this.student.hobby, 0, "籃球")
    
                        // 方式三
                        this.student.hobby.splice(0, 1, "籃球")
                    },
                    removeRap() {
                        this.student.hobby = this.student.hobby.filter(item => {
                            return item !== "rap"
                        })
                    }
                },
            })
        </script>
    </body>
    </html>
    

1.11 收集表單數(shù)據(jù)

<!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>收集表單數(shù)據(jù)</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <!-- 
        收集表單數(shù)據(jù):
            若:<input type="text"/>敌卓,則 v-model收集的是 value 值慎式,用戶輸入的就是 value 值伶氢。
            若:<input type="radio"/>,則 v-model收集的是value值瘪吏,且要給標(biāo)簽配置 value 值癣防。
            若:<input type="checkbox"/>
                1.沒有配置 input 的 value 屬性,那么收集的就是 checked(勾選 or 未勾選掌眠,是布爾值)
                2.配置 input 的 value 屬性:
                    (1)v-model 的初始值是非數(shù)組蕾盯,那么收集的就是 checked(勾選 or 未勾選,是布爾值)
                    (2)v-model 的初始值是數(shù)組蓝丙,那么收集的的就是 value 組成的數(shù)組
            備注:v-model的三個修飾符:
                lazy:失去焦點再收集數(shù)據(jù)
                number:輸入字符串轉(zhuǎn)為有效的數(shù)字
                trim:輸入首尾空格過濾
    -->
    <div id="root">
        <form @submit.prevent="demo">
            <!-- 賬號這么寫的好處是:點擊賬號時级遭,鼠標(biāo)光標(biāo)會自動定位到輸入框內(nèi) -->
            <label for="account">賬號:</label><input type="text" id="account" v-model.trim="userInfo.account"></input></br>
            年齡:<input type="number" v-model.number="userInfo.age"> <br/><br/>
            密碼:<input type="password" v-model="userInfo.password"></input></br>
            性別:
            <input type="radio" name="sex" v-model="userInfo.sex" value="male">男</input>
            <input type="radio" name="sex" v-model="userInfo.sex" value="female">女</input></br>
            愛好:
            <input type="checkbox"  v-model="userInfo.hobby" value="chang">唱</input>
            <input type="checkbox"  v-model="userInfo.hobby" value="tiao">跳</input>
            <input type="checkbox"  v-model="userInfo.hobby" value="rap">Rap</input></br>
            所屬校區(qū)
            <select v-model="userInfo.city">
                <option value="">請選擇校區(qū)</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="shenzhen">深圳</option>
                <option value="wuhan">武漢</option>
            </select>
            <br/><br/>
            其他信息:
            <textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
            <input type="checkbox" v-model="userInfo.agree">閱讀并接受<a >《用戶協(xié)議》</a></br>
            <button>提交</button>
        </form>
    </div>

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

        new Vue({
            el: "#root",
            data: {
                userInfo:{
                    account: '',
                    age: 18,
                    password: '',
                    sex: '',
                    hobby: [],
                    city: '',
                    other: '',
                    agree: ''
                }
            },
            methods: {
                demo(){
                    console.log(JSON.stringify(this.userInfo))
                }
            }

        })
    </script>
</body>
</html>

1.12 過濾器

1.12.1 理解過濾器

  1. 功能:對要顯示的數(shù)據(jù)進行特定格式化后再顯示
  2. 注意:并沒有改變原本的數(shù)據(jù),是產(chǎn)生新的對應(yīng)的數(shù)據(jù)

1.12.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>
    <script src="../js/dayjs.min.js"></script>
</head>
<body>
    <!-- 
        過濾器:
            定義:對要顯示的數(shù)據(jù)進行特定格式化后再顯示(適用于一些簡單邏輯的處理)渺尘。
            語法:
                1.注冊過濾器:Vue.filter(name,callback) 或 new Vue{ filters: {} }
                2.使用過濾器:{{ xxx | 過濾器名}}  或  v-bind:屬性 = "xxx | 過濾器名"
            備注:
                1.過濾器也可以接收額外參數(shù)挫鸽、多個過濾器也可以串聯(lián)
                2.并沒有改變原本的數(shù)據(jù), 是產(chǎn)生新的對應(yīng)的數(shù)據(jù)
    -->
    <div id="root">
        <h2>顯示格式化后的時間</h2>
        <!-- 計算屬性實現(xiàn) -->
        <h3>計算屬性實現(xiàn),現(xiàn)在是{{ fmtTime }}</h3>
        <!-- methods 方法實現(xiàn) -->
        <h3>計算屬性實現(xiàn)鸥跟,現(xiàn)在是{{ getFmtTime() }}</h3>
        <!-- 過濾器實現(xiàn) -->
        <h3>過濾器實現(xiàn)丢郊,現(xiàn)在是{{ fmtTime | timeFormat }}</h3>
        <!-- 過濾器實現(xiàn)(傳參) -->
        <h3>過濾器實現(xiàn)盔沫,現(xiàn)在是{{ fmtTime | timeFormat2("YYYY-MM-DD") | strSlice }}</h3>

    </div>

    <div id="root2">
        <h2>顯示格式化后的時間</h2>
        <!-- 過濾器實現(xiàn)(傳參) -->
        <h3>過濾器實現(xiàn),現(xiàn)在是{{ msg | strSlice }}</h3>
    </div>

    <script>
        // 阻止 vue 在啟動時生成生產(chǎn)提示
        Vue.config.productionTip = false
        // 定義全局過濾器
        Vue.filter('strSlice', function(value) {
            return value.slice(0, 4)
        })

        new Vue({
            el: "#root",
            data: {
                time: Date.now()
            },
            computed: {
                fmtTime() {
                    return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
                }
            },
            methods: {
                getFmtTime() {
                    return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
                }
            },
            // 局部過濾器
            filters: {
                timeFormat() {
                    return dayjs(this.time).format('YYYY_MM_DD HH:mm:ss')
                },
                timeFormat2(val) {
                    return dayjs(this.time).format(val)
                },
                // strSlice(value) {
                //     return value.slice(0, 4)
                // }
            }
        })

        new Vue({
            el: "#root2",
            data: {
                msg: "hello world"
            }
        })
    </script>
</body>
</html>

1.13 內(nèi)置指令與自定義指令

1.13.1 常用內(nèi)置指令

  1. v-text: 更新元素的 textContent
  2. v-html: 更新元素的 innerHTML
  3. v-if: 如果為 true, 當(dāng)前標(biāo)簽才會輸出到頁面
  4. v-else: 如果為 false, 當(dāng)前標(biāo)簽才會輸出到頁面
  5. v-show: 通過控制 display 樣式來控制顯示/隱藏
  6. v-for: 遍歷數(shù)組/對象
  7. v-on: 綁定事件監(jiān)聽,一般簡寫為 @
  8. v-bind: 綁定解析表達式枫匾,可以省略 v-bind
  9. v-model: 雙向數(shù)據(jù)綁定
  10. v-cloak: 防止閃現(xiàn)架诞,與 css 配合: [v-cloak]{display:none}

1.13.2 自定義指令

  1. 注冊全局指令

    Vue.directive('my-directive',function(el,binding){
     el.innerHTML=binding.value.toupperCase()
    })
    
  2. 注冊局部指令

    directives:{
        'my-directive':{
            bind(el,binding){
             el.innerHTML = binding.value.toupperCase()
            }
        }
    }
    
  3. 使用指令

    v-my-directive='xxx'
    

1.14 Vue實例生命周期

1.14.1 生命周期流程圖

lifecycle.png

1.14.2 vue生命周期分析

  1. 初始化顯示
    • beforeCreate()
    • created()
    • beforeMount()
    • mounted()
  2. 更新狀態(tài): this.xxx=value
    • beforeUpdate()
    • updated()
  1. 銷毀 Vue 實例: vm.$destory()
    • beforeDestory()
    • destoryed()

1.14.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>
    <div id="root">
        <h2 v-text="n"></h2>
        <h2>n 的值: {{ n }}</h2>
        <button @click="addN">點我 n + 1</button> <br/>
        <button @click="destroy">點我銷毀 Vm</button>
    </div>

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

        const vm = new Vue({
            el: "#root",
            data: {
                n: 1
            },
            methods: {
                addN() {
                    this.n++ 
                },
                destroy() {
                    console.log("bye...bye... ");
                    // 銷毀 vm 的方式
                    this.$destroy()
                }
            },
            watch: {
                n() {
                    console.log("n 的值發(fā)生改變");
                }
            },
            // 數(shù)據(jù)監(jiān)測、數(shù)據(jù)代理之前干茉,此時無法通過 vm 訪問到 data 中的數(shù)據(jù)谴忧、methods 中的方法
            beforeCreate() {
                console.log("beforeCreate... ")
                console.log("beforeCreate... ", this, this.n) // this.n undefined
                // debugger;
            },
            // 數(shù)據(jù)監(jiān)測、數(shù)據(jù)代理之后等脂,此時可以通過 vm 訪問到 data 中的數(shù)據(jù)俏蛮、methods 中的方法
            created() {
                console.log("created... ");
                console.log("created... ", this, this.n);
                // debugger;
            },
            // 此時頁面呈現(xiàn)的是未經(jīng) Vue 編譯的 DOM 結(jié)構(gòu),所有對 DOM 的操作上遥,最終都不奏效
            beforeMount() {
                console.log("beforeMount... ");
                // debugger; // 模板尚未解析
            },
            // 此時頁面中呈現(xiàn)的經(jīng) Vue 編譯的 DOM搏屑,對 DOM 的操作均有效(盡可能避免)
            // 至此初始化過程結(jié)束
            // 一般在此進行:開啟定時器、發(fā)送網(wǎng)絡(luò)請求粉楚、訂閱消息辣恋、綁定自定義事件等初始化工作
            mounted() {
                console.log("mounted... ")
                // debugger;
            },
            // 此時數(shù)據(jù)是新的,但頁面是舊的模软,即頁面尚未和數(shù)據(jù)保持同步
            beforeUpdate() {
                console.log("beforeUpdate... ")
                // debugger;
            },
            // 此時數(shù)據(jù)是新的伟骨,但頁面也是新的,即頁面和數(shù)據(jù)保持同步
            updated() {
                console.log("updated... ")
                // debugger;
            },
            // 此時 Vm 中的所有 data燃异、methods携狭、指令等等,都處于可用狀態(tài)回俐,馬上要執(zhí)行銷毀過程
            // 一般在此進行:關(guān)閉定時器逛腿、取消訂閱消息、解綁自定義事件等
            beforeDestroy() {
                console.log("beforeDestroy... ")
                // debugger;
            },
            // 銷毀 vm 實例
            destroyed() {
                console.log("destroyed... ")
            },
        })
    </script>
</body>
</html>

1.14.4 常用的生命周期方法

  1. mounted(): 發(fā)送 ajax 請求仅颇,啟動定時器等異步任務(wù)
  2. beforeDestory(): 做收尾工作单默,如:清除定時器
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市忘瓦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耕皮,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粱年,死亡現(xiàn)場離奇詭異逼泣,居然都是意外死亡,警方通過查閱死者的電腦和手機拉庶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吉捶,“玉大人皆尔,你說我怎么就攤上這事呐舔。” “怎么了慷蠕?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵珊拼,是天一觀的道長。 經(jīng)常有香客問我流炕,道長澎现,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任每辟,我火速辦了婚禮剑辫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渠欺。我一直安慰自己妹蔽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布挠将。 她就那樣靜靜地躺著胳岂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捐名。 梳的紋絲不亂的頭發(fā)上旦万,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天闹击,我揣著相機與錄音镶蹋,去河邊找鬼。 笑死拂酣,一個胖子當(dāng)著我的面吹牛婶熬,可吹牛的內(nèi)容都是我干的虽另。 我是一名探鬼主播捂刺,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼仪缸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起锣尉,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤自沧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后孝偎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡势决,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虽抄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朱盐。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡兵琳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出清女,到底是詐尸還是另有隱情嫡丙,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站惠窄,受9級特大地震影響杆融,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜介劫,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望踢京。 院中可真熱鬧黔帕,春花似錦成黄、人聲如沸奋岁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畜份。三九已至漂坏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驯绎,已是汗流浹背剩失。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像估脆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子朦拖,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355