Vue學習知識點總結

Vue講解

Vue 是一套用于構建用戶界面的漸進式框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關注視圖層,不僅易于上手,還便于與第三方庫或既有項目整合。另一方面,Vue 也完全能夠為復雜的單頁應用提供驅動。有些知識點Vue官網講解的不是很清晰,所以我就寫了一些小的demo;但是官網上有些知識點這里是沒有講解到的,大神請坐高鐵走!小白每天抽空看一遍,不會也會了!

案例地址: https://github.com/pengjunshan/WebPJS/Vue

其它Web文章
CSS浮動的使用和解決浮動的五種方法
CSS定位relative、absolute、fixed使用總結
原生開發WebApi知識點總結
開發中常用jQuery知識點總結
C3動畫+H5+Flex布局使用總結
ES6常用知識總結
開發環境到生產環境配置webpack
待續......

本編文章會講到的知識點
  • Vue基礎使用
    • vue的使用
    • Mustache表達式使用
    • 指令v-使用
    • 動態添加數據到data、異步更新DOM
    • filter過濾器
    • watch監聽配置項
    • computed計算屬性配置項
    • 事件修飾符
    • 鍵值修飾符
    • vue聲明周期鉤子函數
    • 自定義指令
    • 小案例
  • vue組件
    • 全局組件
    • 局部組件
    • 父組件傳遞子組件數據
    • 子組件傳遞父組件數據
    • 非父子組件傳遞數據
    • 組件中插槽使用
    • vue中ref使用
  • vue-router路由
    • 路由基本使用
    • 重定向、高亮
    • 路由傳參方式
    • 路由嵌套-子路由
  • vuex
    • State
    • Mutation
    • Action
    • Getter
Vue基礎使用
1.vue的使用

下載Vue:npm i vue

  1. 首先下載vue,引入vue.js
  2. js中創建一個Vue對象實例
  3. 通過el指定vue管理頁面的邊界
  <!-- 引入vue.js文件 -->
   <script src="lib/vue.js"></script>
   <div id="app">
        <input v-model="message" type="text"><br>
        <h1>{{message}}</h1>
    </div>

    <!-- 下載Vue:npm i vue -->
    <script>
        var vm = new Vue({
            /**
            *   el是element的簡寫,用來指定vue管理頁面的邊界,
            *   也就是說只有包裹在 #app內部的元素,才會收到Vue的管理!!!
            */
            el: '#app',

            /**
            *   頁面中用的到數據都放到data對象中
            */
            data: {
                message: '鄧紫棋喜歡你'
            }

            // 寫Vue可能會遇到的錯誤:
            // 1 注意:Vue 是以大寫字母開頭的,它是一個構造函數!!!
            // 2 注意:在 Vue 中,HTML屬性值無法使用 {{}}!!!
            // 3 開發期間一定要使用未壓縮版的Vue(開發版)
        })

        /**
        *   vm是Vue的對象實例,可以通過vm.$data.屬性名獲取data中的屬性值,可以省略$data
        */
        console.log(vm.message)
        console.log(vm.$data.message)
        console.log(vm.message === vm.$data.message)
Mustache表達式使用

雙花括號{{}} 就是 mustache語法,用于展示data中的內容,mustache 中可以出現任意的 JS表達式;

  • 表達式{{}}只能從數據對象data中獲取數據;
  • mustache中不能出現語句,比如:if () {} / for(var i =0 ...) {} / var num = 1;
  • Mustache 語法不能作用在 HTML 元素的屬性上;
 <div id="app">
            <h1>{{ msg }}</h1>
            <p>{{ 1 + 2 }}</p>
            <p>{{ ['a', 'c', 'b'] }}</p>
            <p>{{ ['a', 'c', 'b'].join('-') }}</p>
            <p>{{ msg + ' -- 拼接內容' }}</p>
            <p>{{ age > 18 ? '成年了' : '未成年' }}</p>
            <p>{{ Math.random() }}</p>
    </div>
    <script>
        var vm = new Vue({
            el:'#app',
            data:{
                msg:'鄧紫棋金魚嘴',
                age:19
            }
        })
    </script>
指令v-使用

指令 (Directives) 是帶有 v- 前綴的特殊屬性,當表達式的值改變時,將其產生的連帶影響,響應式地作用于 DOM。

1.v-text

用來設置當前元素的文本內容,相當于DOM對象的 innerText或textContent

 <div v-text='msg'></div>

2.v-html

更新DOM對象的 innerHTML

 <div v-html='htmlMsg'></div>

3.v-bind

通過v-bind為HTML元素綁定屬性,使用data中提供的數據;
因為 v-bind:title 這種使用方式很繁瑣,所以,vue提供了一個簡化語法 :title

<img v-bind:title='msg' v-bind:src='imgPath' v-bind:name='name'>
<img :title='msg' :src='imgPath' :name='name'>

4.v-on

綁定事件,支持js所有的事件類型, v-on綁定的事件方法都要寫在Vue實例中的methods對象中;
v-on:省略寫 @

<button v-on:click='getData'>點我</button><input v-on:onfocus='getFocus'>
<button @click='getData'>點我</button><input @onfocus='getFocus'>

5.v-model

在表單元素上創建雙向數據綁定;
只能用在表單元素中,注意:不同的表達元素,v-model的表現可能會有所不同。
比如:v-model操作文本框的value屬性,而復選框 v-model 就是操作其選中狀態;

        <!-- 綁定的是文本框輸入的內容 -->
        <input type="text" v-model='msg'>
        <!-- 綁定的是復選框是否選中 -->
        <input type="checkbox" v-model='isCheck'>

6.v-for

基于源數據多次渲染元素或模板塊,不僅可以渲染集合List也可以遍歷對象Obj;

      <!-- v-for 遍歷list集合-->
       <ul>
            <!--1.item是每一項對象
                使用 v-for 的時候提供 key 屬性,以獲得性能提升。
            -->
            <li v-for='item in list' :key='item.key'>
                姓名:{{item.name}} -- 年齡:{{item.age}}
            </li>

            <!--2.item 為當前項,index 為索引 -->
            <li v-for='(item,index) in list'>
                姓名:{{item.name}} -- 年齡:{{item.age}} -- 下標:{{index}}
            </li>
        </ul>

       <!-- v-for Obj對象 value,key,index順序不能變 -->
        <ul>
            <li v-for='(value,key,index) in csObj'>
                key={{key}} -- value={{value}} -- index={{index}}
            </li>
        </ul>

7.v-bind:class和v-bind:style

表達式的類型:字符串、數組、對象(重點)

      <!-- 可以是對象,key是類名 value是布爾值,如果是true就添加這個類,否則就不添加-->
        <h2 :class='{pink:true,green:true}'>中國驚奇先生</h2>
      <!-- 可以是數組,-->
        <h2 :class='['pink','fz','green']'>斗羅大陸</h2>
        <h2 :style="{ color: activeColor, 'font-size': fontSize + 'px' }">不良人</h2>

8.v-if

根據表達式布爾值的真假條件是否加載這段代碼, true:DOM中會加載這段代碼,false:DOM中不會加載這段代碼;

 <h3 v-if='isIF'>我是v-if,是否會加載我</h3>

9.v-show

根據表達式之真假值,切換元素的 display CSS 屬性,無論true還是false DOM中都會加載這段代碼;

<h3 v-show='isShow'>我是v-show,是否會顯示出來
</h3>

10.v-pre

跳過這個元素和它的子元素的編譯過程。可以用來顯示原始 Mustache 標簽。跳過大量沒有指令的節點會加快編譯。

<!--測試:頁面中的msg不會顯示data中的內容,因為跳過了表達式編譯-->
 <div v-pre>v-pre跳過編譯過程 {{msg}}</div>

11.v-once

只渲染元素和組件一次。隨后的重新渲染,元素/組件及其所有的子節點將被視為靜態內容并跳過。

    <!--測試:在控制臺通過vm對象修改msg,頁面顯示中的msg內容不會有變化-->
        <div v-once>v-once跳過編譯過程 {{msg}}</div>

12.v-cloak

頁面中使用 {{}} 的時候,經歷了由 {{}} -> 具體內同,這么一個過程,所以頁面會造成“閃爍”
解決:通過添加 v-cloak 指令,配合 [v-cloak] { display: none; } 避免了頁面閃爍

        <div v-cloak>{{msg}}</div>
動態添加數據到data、異步更新DOM

1.動態添加數據到data

只有data中的數據才是響應式的,動態添加進來的數據默認為非響應式

可以通過以下方式實現動態添加數據的響應式:

  • 1 Vue.set(object, key, value) - 適用于添加單個屬性
  • 2 Object.assign() - 適用于添加多個屬性

2.異步更新DOM

當綁定的數據發生變動時,Vue 異步執行 DOM 更新,監視所有數據改變,一次性更新DOM;

解決方法:

  • Vue.nextTick
  • this.$nextTick
 <div id="app">
        <!-- 點擊按鈕之前data中還沒有age屬性 -->
        <button @click='addAge'>給data添加age</button>
        <div>名字:{{stu.name}}</div>
        <!-- 
            這里使用的表達式中的屬性必須是響應式的
            只有data中的數據才是響應式的,動態添加進來的數據默認為非響應式 
        -->
        <div>年齡:{{stu.age}}</div>
        <div>性別:{{stu.sex}}</div>
    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'hello vue',
                stu: {
                    name: 'jack',
                }
            },
            methods: {
                addAge: function () {
                    //可以通過以下方式實現動態添加數據的響應式
                    //1.添加單個屬性
                    // 第一個參數:表示要給哪個對象添加響應式屬性 $data可以省略
                    // 第二個參數:表示要添加的屬性名稱
                    // 第三個參數:表示屬性的值
                    Vue.set(this.stu, "age", 18)
                    //2.添加多個屬性
                    //第一個參數:是一個空對象
                    //第二個參數:添加到哪個對象
                    //第三個參數:添加屬性的對象
                    this.stu = Object.assign({},this.stu,{"name":"鄧紫棋","age":18,"sex":"man"})

                    //此時打印的內容為 名字:jeck
                    //
                    //為什么呢? Vue 異步執行 DOM 更新,監視所有數據改變,一次性更新DOM
                    console.log(this.$el.children[1].innerText)

                    //解決方法 Vue.nextTick 和 this.$nextTick 是相同的
                    //在DOM更新后,回調執行某個操作(DOM操作
                    this.$nextTick(function(){
                        console.log(this.$el.children[1].innerText)
                    })
                }
            }
        })
    </script>
filter過濾器
  • 作用:文本數據格式化 , 也就是: 將數據按照我們指定的一種格式輸出
  • 過濾器可以用在兩個地方:{{}}表達式 和 v-bind 指令中
  • 兩種過濾器:1 全局過濾器 2 局部過濾器

1.全局過濾器

  • 說明:通過全局方式創建的過濾器,在任何一個vue實例中都可以使用
  • 注意:使用全局過濾器的時候,需要先創建全局過濾器,再創建Vue實例
<div>{{ dateStr | date }}</div>
<div>{{ dateStr | date('YYYY-MM-DD hh:mm:ss') }}</div>
<script>
  Vue.filter('date', function(value, format) {
    // value 要過濾的字符串內容,比如:dateStr
    // format 過濾器的參數,比如:'YYYY-MM-DD hh:mm:ss'
  })

var vm = new Vue({
})
</script>

2.局部過濾器

  • 說明:局部過濾器是在某一個vue實例的內容創建的,只在當前實例中起作用
  <div>{{msg | fi("九")}}</div>
  var vm = new Vue({
            el:'#app',
            data:{
                msg:'八百個標兵奔北坡,八百個標兵奔北坡'
            },
            //2. 局部過濾器 只有在當前Vue實例中才起作用
            // 通過 filters 配置項, 來創建過濾器
            filters:{
                // content是內容,format是過濾的規則可以多個參數
                fi:function(content,format){
                    return content.replace(/八/g,format);
                }
            }
        })
watch監聽配置項
  • 概述:watch是一個對象,鍵是需要觀察的表達式,值是對應回調函數
  • 作用:當表達式的值發生變化后,會調用對應的回調函數完成響應的監視操作
 <div id="app">
        <input type="text" v-model='userName'>
        <p v-show='isError'>請輸入4-8位字符</p>
        <input type="text" v-model='stu.age'>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                userName: '',
                isError: false,
                stu: {
                    age: 10,
                }
            },
            // 通過 watch 配置項,來監視數據變化
            // 只能監視 data 中的數據,要監視的數據,作為watch的屬性
            watch: {
                // 監視userName值的變化,方法名要用要監視的值的名字
                userName:function(curVal, oldVal){
                    console.log('當前值為:', curVal, '上一次值為:', oldVal);
                    if(curVal.length>=4 && curVal.length<=8){
                        this.isError = false;
                    }else{
                        this.isError = true;
                    }
                },
                // 監聽對象,加上deep:true
                // 注意:如果監視對象的變化,那么,curVal 和 oldVal 是相同的,指向同一個對象
                stu:{
                    handler:function(curVal, oldVal){
                        console.log('當前值為:', curVal, '上一次值為:', oldVal);
                    },
                    deep: true
                },
                // 一般都是監聽對象中的屬性
                // 只需要監視某個屬性的變化,而不是整個對象中所有的屬性的變化
                'stu.age':function(curVal, oldVal){
                    console.log('當前值為:', curVal, '上一次值為:', oldVal);
                }
            }
        })
    </script>
computed計算屬性配置項
  • 說明:計算屬性是基于它們的依賴進行緩存的,只有在它的依賴發生改變時才會重新求值
  • 注意:Mustache語法({{}})中不要放入太多的邏輯,否則會讓模板過重、難以理解和維護
  • 注意:computed中的屬性不能與data中的屬性同名,否則會報錯
 <div id="app">
        <input type="text" v-model='num1'>+
        <input type="text" v-model='num2'>=
        <input type="text" v-model='result'>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                num1: 0,
                num2: 0,
                // result: 0 計算屬性名不能和data中的屬性相同
            },
            // 計算屬性,通過 computed 配置項來指定
            // 注意:計算屬性不能與data中的屬性相同!!!否則會報錯
            // 特點:計算屬性依賴的屬性(比如:num1 和 num2)發生改變,那么計算屬性就會被重新計算
            // 優勢:內部使用緩存機制,如果頁面中多個地方都用到了計算屬性,那么計算屬性只會被重新計算一次!!!
            computed: {
                result:function(){
                    return (this.num1-0)+(this.num2-0);
                }
            }
        })
    </script>
事件修飾符
  • .stop 阻止向上冒泡 不會調用父的事件
  • .prevent 阻止默認行為,調用 event.preventDefault()
  • .capture捕獲冒泡
  • .self 只當事件在該元素本身觸發時,才會觸發事件
  • .once 事件只觸發一次
 <!-- .stop 阻止向上冒泡 不會調用父的事件 -->
        <div @click='cathFather'>我是父事件修飾符
            <!-- .stop  阻止冒泡,調用 event.stopPropagation() -->
            <div @click.stop='catchSon'>我是子事件修飾符</div>
        </div>

        <!-- .prevent 阻止默認行為,調用 event.preventDefault() -->
        <a  @click.prevent='onPrevent'>我是prevent事件</a>

        <!-- .capture捕獲冒泡,
            即有冒泡發生時,有該修飾符的dom元素會先執行,如果有多個,從外到內依次執行,然后再按自然順序執行觸發的事件。
        -->
        <!-- 如果不給爺爺添加capture 點擊兒子觸發的順序是 兒子、爸爸、爺爺 -->
        <!-- 給爺爺添加了capture事件后 點擊兒子觸發的順序是 爺爺、兒子、爸爸 -->
        <div @click.capture='grandpa'>我是爺爺
            <div @click='father'>我是爸爸
                <div @click='son'>
                        我是兒子
                </div>
            </div>
        </div>

        <!-- .self 只當事件在該元素本身觸發時,才會觸發事件 -->
        <div @click.self='onSelfFather'>self事件爸爸
            <div @click='onSelfSon'>self事件兒子</div>
        </div>

        <!-- .once  事件只觸發一次 -->
        <div @click.once='onOnce'>再點我一次試試</div>
鍵值修飾符
  • 說明:在監聽鍵盤事件時,Vue 允許為 v-on 在監聽鍵盤事件時添加關鍵修飾符
   <div id="app">
        <!-- 鍵值修飾符 包括鍵盤、鼠標 -->
        <!-- 13是Enter鍵的code值 -->
        <input type="text" v-model='msg' @keyup.13='submit'>
        <input type="text" v-model='msg2' @keyup.enter='submit2'><br>
        <!-- 使用自定義鍵值修飾符 -->
        <input type="text" v-model='msg' @keyup.f2='submit'>
    </div>

    <script>
        // 自定義鍵值修飾符 有時候寫code值是數字的時候并沒有語義,所有我們給它定義一下
        Vue.config.keyCodes.f2 = 113;
        var vm = new Vue({
            el:'#app',
            data:{
                msg:'',
                msg2:''
            },
            methods:{
                submit:function(){
                    console.log('提交數據='+this.msg)
                },
                submit2:function(){
                    console.log('提交數據='+this.msg2)
                },
            }
        })
    </script>
vue聲明周期鉤子函數

beforeCreate()

  • 說明:在實例初始化之后,數據觀測 (data observer) 和 event/watcher 事件配置之前被調用
  • 注意:此時,無法獲取 data中的數據、methods中的方法
  • 使用場景:可以在這個鉤子函數中開啟頁面加載的 loading 效果

created()

  • 注意:這是一個常用的生命周期,可以調用methods中的方法、改變data中的數據
  • 使用場景:發送請求獲取數據

beforeMounted()

  • 說明:組件將要掛載到頁面中,也就是說:組件的內容還沒有被掛載到頁面中
  • 注意:此時,獲取不到頁面中DOM元素

mounted()

  • 說明:組件已經被掛載到頁面中,此時,可以進行DOM操作了

beforeUpdate()

  • 說明:數據更新時調用,發生在虛擬 DOM 重新渲染和打補丁之前。你可以在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染過程。

updated()

  • 說明:組件 DOM 已經更新完成,所以你現在可以執行依賴于 DOM 的操作。

beforeDestroy()

  • 說明:實例銷毀之前調用。在這一步,實例仍然完全可用。
  • 使用:實例銷毀之前,執行清理任務,比如:清除定時器等

destroyed()

  • 說明:Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。
自定義指令

Vue這種MVVM模式的框架不推薦開發人員直接手動操作DOM有些情況, 還是需要操作DOM的, 如果需要操作DOM, 就通過 Vue中的自定義指令來操作!!!

通過Vue.directive()方法自定義指令:

  • 第一個參數: 表示自定義指令的名稱;
  • 第二個參數 1.表示自定義指令運行的時候, 需要執行的邏輯操作;
 Vue.directive('ff1', function (el) {
            console.log(el)
        })
  • 第二個參數 2.還可以是一個對象,對象中是指令的鉤子函數;
 Vue.directive('ff2', {
            // bind 和 inserted 這兩個鉤子函數, 都是進入頁面就立即執行的
            // 區別:inserted 能獲取到指令所在元素的父元素,bind 獲取不到父元素
            bind(el) {
                console.log('bind', el.parentNode)
            },
            inserted(el) {
                console.log('inserted', el.parentNode)
            })}

指令函數的入參:

        <!-- 標識放到自定義指令的后面 .表示名 -->
        <!-- 注意:如果 v-color="red" 那么,red指的值:data中的red屬性 -->
        <div v-color.back=" 'blue' ">{{ msg }}</div>
        <div v-color.col=" 'red' ">{{ msg }}</div>
      Vue.directive('color', function (el, binding) {
            if (binding.modifiers.col) {
                el.style.color = binding.value
            } else {
                el.style.backgroundColor = binding.value
            }
        })

小案例

案例請到https://github.com/pengjunshan/WebPJS中查看

案例

Vue組件

組件是可復用的 Vue 實例,組件分為全局組件和局部組件。因為組件是可復用的 Vue 實例,所以它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命周期鉤子等,el 是根實例特有的屬性,組件中沒有。

全局組件

全局組件在所有的vue實例中都可以使用,注意:先注冊組件,再初始化根實例。

Vue.component('name',{配置項})

  • 第一個參數是組件名
  • 第二個參數是組件的配置項,與Vue根實例配置項差不多
  • 組件中的data必須是個函數數據用return返回,Vue跟實例中的data是個對象
  • 組件中template模板有兩種方式,“字符串” “html模板”
<body>
    <div id="app">
        <hello></hello>
    </div>

    <template id="temp">
        <div>
            <p>我是組件:{{msg}}</p>
            <button @click='fn'> 點擊消滅新冠 </button>
        </div>
    </template>
    <script>

        /**
        * 第一個參數是組件名
        * 第二個參數是配置項,與Vue實例的配置幾乎一樣
        */
        Vue.component('hello', {
            //template是組件的模板 也就是要展示的內容
            //組件中template模板有兩種方式,“字符串” “html模板”
            //方式一:字符串
            // template: `
            //     <div>
            //         <p>我是組件:{{msg}}</p>
            //         <button @click='fn'> 點擊消滅新冠 </button>
            //     </div>
            // `,
            //方式二:html模板
            template: '#temp',

            //組件中的data必須是個函數數據用return返回,Vue跟實例中的data是個對象
            data() {
                return {
                    msg: '武漢加油 中國加油'
                }
            },
            methods: {
                fn() {
                    this.msg = '新冠被消滅了,中國威武'
                }
            }
        })
        var vm = new Vue({
            el: '#app',
            data: {}
        })
    </script>
</body>
局部組件

局部組件,是在某一個具體的vue實例中定義的,只能在這個vue實例中使用;在Vue實例中使用components對象創建組件,可以創建多個組件;

<body>
    <div id="app">
        <!-- hello組件 -->
        <hello></hello>
        <!-- love組件 -->
        <love></love>
    </div>

    <template id="temp">
        <div>
            <p>我是組件222:{{msg}}</p>
            <button @click='fn'> 點擊消滅新冠 </button>
        </div>
    </template>

    <script>

        //1.局部組件,是在某一個具體的vue實例中定義的,只能在這個vue實例中使用
        //2.在Vue實例中使用components對象創建組件,可以創建多個組件
        //3.組件中template模板有兩種方式,“字符串” “html模板”

        var vm = new Vue({
            el: '#app',
            data: {
            },
            components: {
                //hello 組件名
                'hello': {
                    //方式一 字符串
                    template: `
                        <div>
                            <p>我是組件111:{{msg}}</p>
                            <button @click='fn'> 點擊消滅新冠 </button>
                        </div>
                    `,
                    data() {
                        return {
                            msg: '武漢加油 中國加油'
                        }
                    },
                    methods: {
                        fn() {
                            this.msg = '新冠被消滅了,中國威武'
                        }
                    }
                },
                'love': {
                    //方式二 引用html中的代碼模板
                    template: '#temp',
                    data() {
                        return {
                            msg: '我們愛中國 愛武漢'
                        }
                    },
                    methods: {
                        fn() {
                            this.msg = '我們愛中華民族'
                        }
                    }
                }

            }
        })
    </script>
</body>
父組件傳遞子組件數據
  • 方式:通過props屬性來傳遞數據
  • 注意:屬性的值必須在組件中通過props屬性顯示指定,否則,不會生效
  • 說明:傳遞過來的props屬性的用法與data屬性的用法相同
  • 如果傳遞的數據是data中的屬性時,必須使用v-bind綁定屬性才可以傳遞過去
<body>
    <div id="app">
        <hello mm='中華民族萬歲'></hello>
        <!-- 如果傳遞的數據是data中的屬性時,必須使用v-bind綁定屬性才可以傳遞過去 -->
        <!-- <hello zz='msg'></hello> -->
        <hello v-bind:zz='msg'></hello>
    </div>

    <script>

        // 父組件 傳遞數據給 子組件:(父組件:Vue的實例對象,子組件:hello組件)
        // 原理:通過 props 屬性來傳遞
        // 注意:使用父組件傳遞的屬性方式和使用data中的屬性方式一樣
        Vue.component('hello', {
            template: `
                <div>
                    <p>我是組件:{{msg}}</p>
                    <p v-if='mm'>我接收到父組件的內容:{{mm}}</P>
                    <p v-if='zz'>我接收到父組件的內容:{{zz}}</P>
                    <button @click='fn'> 點擊消滅新冠 </button>
                </div>
            `,
            //指定props中的值,來接收父組件傳遞過來的值
            props:['mm','zz'],
            data() {
                return {
                    msg: '武漢加油 中國加油'
                }
            },
            methods: {
                fn() {
                    this.msg=this.msg+'-----'+(this.mm===undefined? this.zz:this.mm);
                }
            }
        })
        var vm = new Vue({
            el: '#app',
            data: {
                msg:'浙江杭州'
            }
        })
    </script>
</body>
子組件傳遞父組件數據
  • 方式:父組件給子組件傳遞一個函數,由子組件調用這個函數
  • 說明:借助vue中的自定義事件(v-on:cunstomFn="fn")
  • $emit():觸發事件
<body>
    <div id="app">
        <p>{{msg}}</p>
        <hello @pfn='parentFn'></hello>
    </div>
    <template id="temp">
        <div>
            <p>我是組件:{{msg}}</p>
            <button @click='sonFn'> 點擊消滅新冠 </button>
        </div>
    </template>
    <script>
        //組件傳遞 子》父
        //1.由父組件定義一個方法,通過@pfn傳給子組件
        //2.子組件通過$emit方法把數據傳遞給父組件定義的方法

        Vue.component('hello', {
            template: '#temp',
            data() {
                return {
                    msg: '武漢加油 中國加油'
                }
            },
            methods: {
                sonFn() {
                    //通過$emit方法傳遞數據給父組件的方法,參數可以為多個
                    this.$emit('pfn', '新冠被消滅了,中國威武', '測試')
                }
            }
        })

        var vm = new Vue({
            el: '#app',
            data: {
                msg: '標題'
            },
            methods: {
                parentFn(data, data2) {
                    this.msg = data;
                    console.log(data2)
                }
            },
        })
    </script>
</body>
非父子組件傳遞數據
  • 可以使用一個空的 Vue 實例作為事件總線bus
  • A組件傳遞B組件數據 1.B先通過bus.$on綁定事件,2.A通過bus.$emit方法調用B綁定的事件方法
  • $on和$emit都是bus調用的
<body>
    <div id="app">
        <aaa></aaa>
        <bbb></bbb>
    </div>
    <script>
        //可以使用一個空的 Vue 實例作為事件總線
        var bus = new Vue()
        //A組件傳遞B組件數據 1.B先通過bus.$on綁定事件,2.A通過bus.$emit方法調用B綁定的事件方法
        //$on和$emit都是bus調用的
        var vm = new Vue({
            el: '#app',
            data: {},
            components: {
                aaa: {
                    template: `
                        <div>
                            <h3>我是組件AA</h3>
                            <button @click='fn'> 點我傳給B數據 </button>
                        </div>
                    `,
                    data() {
                        return {
                            msg: 'A組件'
                        }
                    },
                    methods: {
                        fn() {
                            bus.$emit('bfn', '組件A說:你好組件B')
                        }
                    }

                },
                bbb: {
                    template: `
                        <div>
                            <h3>我是組件BB</h3>
                            <p>{{msg}}</p>
                        </div>
                    `,
                    data() {
                        return {
                            msg: '我在等待數據...'
                        }
                    },
                    created() {
                        //綁定事件 接收數據,當進入頁面時走到這個鉤子函數后就自動綁定事件了
                        bus.$on('bfn', data => {
                            this.msg = data
                        })
                    }
                }
            }
        })
    </script>
</body>
組件中插槽使用

有時在使用組件的時候希望往組件中加入其它內容,在組件中通過插槽<slot></slot>來接收內容。插槽內可以包含任何模板代碼,包括 HTML,甚至其它的組件;

<body>
  <div id="app">
    <hello>
      <p>趕走新冠</p>
    </hello>
  </div>

  <template id="temp">
    <div>
      <p>{{msg}}</p>
      <slot></slot>
      <slot></slot>
    </div>
  </template>

  <script>

    //當組件渲染的時候,<slot></slot> 將會被替換為"趕走新冠"。插槽內可以包含任何模板代碼
    //可以有多個插槽
    Vue.component('hello',{
      template:'#temp',
      data(){
        return{
          msg:'武漢加油 中國加油'
        }
      }
    })
    var vm = new Vue({
      el: '#app',
      data: {
        msg:'趕走新冠'
      }
    })
  </script>
</body>
vue中ref使用

使用ref注冊后 可以使用this.$refs獲取當前DOM對象,必須在mounted()鉤子函數之后才可以獲取DOM對象;元素和組件都可以使用ref注冊;

<body>
    <div id="app">
        <!-- 使用ref注冊后  可以使用this.$refs.pp獲取當前DOM對象 -->
        <p ref='pp'>哈嘍,大家好</p>

        <!-- 組件也可以 -->
        <hello ref="ho"></hello>
    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            components: {
                hello: {
                    template: `<h1>大家好</h1>`,
                    data() {
                        return {
                            msg: 'hello message'
                        }
                    },
                    methods: {
                        fn() {
                            console.log("觸發了事件11111")
                        }
                    }
                }
            },
            mounted() {
                console.log(this.$refs.pp)
                this.$refs.pp.style.color = 'red';

                console.log(this.$refs.ho.msg)
                this.$refs.ho.fn()
            }
        })
    </script>
</body>
vue-router路由
路由基本使用
  • 1.在當前文件夾下執行npm init、npm init -y初始化package.json
  • 2.然后執行npm i -s vue、npm i -s vue-router安裝vue和vue-router
  • 3.在node_modules下找到vue和vue-router中的js并引入到項目中
  • 4.創建組件
  • 5.創建路由對象,并配置路由
  • 6.在Vue實例中關聯router
  • 7.路由入口
  • 8.路由出口
<body>
    <div id="app">
        <!-- 6.路由入口 -->
        <router-link to='/home'>首頁</router-link>
        <router-link to='/me'>我的</router-link>
        <!-- 7.路由出口 -->
        <router-view></router-view>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script src="./node_modules/vue-router/dist/vue-router.js"></script>
    <script>
        //首先先安裝vue和vue-router
        //1.在當前文件夾下執行npm init、npm init -y初始化package.json
        //2.然后執行npm i -s vue、npm i -s vue-router安裝vue和vue-router
        //3.在node_modules下找到vue和vue-router中的js并引入到項目中
        //4.先創建兩個組件
        const Home = Vue.component('home', {
            template: `<h1>我是Home組件</h1>`
        })
        const Me = Vue.component('me', {
            template: `<h1>我是Me組件</h1>`
        })
        //5.創建路由對象
        const router = new VueRouter({
            routes: [
                { path: '/home', component: Home },
                { path: '/me', component: Me }
            ]
        })
        var vm = new Vue({
            el: '#app',
            data: {},
            //將vue和router
            router: router
        })
    </script>
</body>
重定向、高亮

當第一次打開頁面時,想要默認打開一個路由,就可以使用路由中的重定向;按鈕的高亮樣式不是我們喜歡的,可以使用linkActiveClass來自定義高亮元素的類名,然后再設置css樣式就可以了;

 //5.創建路由對象
        const router = new VueRouter({
            routes: [
                //如果當前路徑是'/'就redirect重定向 默認home組件
                { path: '/', redirect: '/home' },
                { path: '/home', component: Home },
                { path: '/me', component: Me }
            ],
            // 修改默認高亮的a標簽的類名
            // 如果是配合第三方組件庫來實現菜單高亮,此時,只需要將類名設置為 第三方組件的類名即可
            linkActiveClass: 'now'
        })
 <style>
        /* .router-link-exact-active, */
        /* .router-link-active { */
        .now {
            color: hotpink;
            font-size: 30px;
            text-decoration: none;
        }
    </style>
路由傳參方式

有時候多個路由都打開同一個組件,可以通過給組件傳不同的參數展示不同的內容就可以了;通過路由打開不同組件傳參也是一樣的;
導航分為兩種

  • 1.聲明式導航(router-link)
  • 2.編程式導航($router.push)

聲明式導航(router-link)

  • to字符串:只能傳遞字符串
  • :to對象:可以傳遞對象,可以通過name、path方式

編程式導航($router.push)

  • this.router.push(name,params);通過name跳轉的狀態欄里看不到參數類似post;組件通過route.params獲取參數;
  • this.router.push(path,query);通過path跳轉的狀態欄里可以看到參數類似get;組件通過route.query獲取參數;

監聽路由變化

在組件中通過watch對象中監聽路由的變化$route(to, from) {},在這里可進行監聽數據變化 進行網絡請求等等;

詳細使用方式請看下面代碼

<body>
    <div id="app">
        <!-- 通過to字符串 -->
        <router-link to="/home/1001">1001號賽車</router-link>
        <router-link to="/home/1002">1002號賽車</router-link>
        <!-- 通過$router.push{} -->
        <a @click='fn'>1003號賽車</a>
        <a @click='fn1'>1004號賽車</a>
        <!-- 通過:to對象 -->
        <router-link :to="{ name:'Home',params:{id:1005,title:'pjs'}}">1005</router-link>
        <router-link :to="{ path:'/home',query:{id:1006,title:'pjs'}}">1006</router-link>

        <router-view></router-view>
    </div>

    <script>
        //導航分為兩種:1.聲明式導航(router-link)  2.編程式導航($router.push)
        //1.通過to字符串
        //2.$router.push{}
        //3.通過:to對象

        //通過name跳轉的狀態欄里看不到參數類似post,通過path跳轉的狀態欄里可以看到參數類似get
        //通過$route.params或$route.query來獲取參數
        const Home = Vue.component('home', {
            template: `
                <div>
                    <h1 v-if='$route.params.id'>歡迎來到主頁面{{ $route.params.id}}</h1>
                    <h1 v-if='$route.query.id'>歡迎來到主頁面{{ $route.query.id}}</h1>
                </div>
            `,
            //監聽路由變化,獲取參數進行操作
            watch: {
                 //只要路由發生的變化就會執行這個方法,to 跳轉的目的地, from 從哪里來
                $route(to, from) {
                    //在這里可進行監聽數據變化 進行網絡請求
                    console.log(to)
                    console.log(from)
                    console.log(to.params.id)
                    console.log(to.query.id)
                }
            }
        })

        const router = new VueRouter({
            routes: [
                { path: '/home/:id', component: Home },
                { path: '/home', name: 'Home', component: Home }
            ]
        })

        var vm = new Vue({
            el: '#app',
            router,
            methods: {
                fn() {
                    this.$router.push({
                        name: 'Home',//找到routes里匹配到name為Home
                        params: {
                            id: 1003,
                            title: 'pjs'
                        }
                    })
                },
                fn1() {
                    this.$router.push({
                        path: '/home',
                        query: {
                            id: 1004,
                            title: 'pjs'
                        }
                    })
                }
            }
        })
    </script>
</body>
路由嵌套-子路由
  • 路由是可以嵌套的,即:路由中又包含子路由
  • 規則:父組件中包含 router-view,在路由規則中使用 children 配置
  • 使用children里配置子路由,子路由的path里不需要加/符號了
<body>
    <div id="app">
        <router-link to='/home'>首頁</router-link>
        <router-link to='/user'>我的</router-link>
        <router-view></router-view>
    </div>

    <script>

        //路由是可以嵌套的,即:路由中又包含子路由
        //規則:父組件中包含 router-view,在路由規則中使用 children 配置
        const Home = Vue.component('home', {
            template: `
                <div>
                    <router-link to='/home/cartA'>買車</router-link>
                    <router-link to='/home/cartB'>賣車</router-link>
                    <router-view></router-view>
                </div>
            `
        })
        const CartA = {
            template: `<h3>買什么樣的車?</h3>`
        }
        const CartB = {
            template: `<h3>賣什么樣的車?</h3>`
        }
        const User = Vue.component('user', {
            template: `
                <div>
                    這里是個人信息
                </div>
            `
        })
        const router = new VueRouter({
            routes: [
                {
                    path: '/home', component: Home,
                    //使用children里配置子路由,子路由的path里不需要加/符號了
                    children: [
                        {
                            path: 'cartA',
                            component: CartA
                        },
                        {
                            path:'cartB',
                            component:CartB
                        }
                    ]
                },
                { path: '/user', component: User }
            ]
        })
        var vm = new Vue({
            el: '#app',
            router
        })
    </script>
</body>
vuex

Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。意思就是所有組件共同操作一份數據,都可以對它進行增刪改查。
屬性|作用
:---:|:---:
State|共享數據都存在這里
Mutation|更改State中數據的唯一方法,同步操作

Action|異步操作Mutation來更改State中的數據
Getter|基于state的派生狀態,可理解為組件中的計算屬性

State

1.安裝vuex npm i -s vuex
2.創建store對象
3.把vue和store進行關聯
4.使用$store.state中的數據

<body>
    <div id="app">
        <!-- 4.使用$store.state中的數據 -->
        <h1>{{this.$store.state.name}}</h1>
    </div>
    <script>
        //1.安裝vuex npm i -s vuex
        //2.創建store對象
        let store = new Vuex.Store({
            /**
            *   state中可以存儲任何類型的值
            */
            state: {
                name: '鄧紫棋'
            }
        })
        let vm = new Vue({
            el: '#app',
            data: {},
            //3.把vue和store進行關聯
            store,
            mounted() {
                //可以獲取store對象
                console.log(this.$store)
            }
        })
    </script>
</body>
state使用
Mutation

mutation是更改store中狀態的唯一方法,vuex中規定只能通過提交mutation的方式去更改store中的狀態,store.commit()方法更改數據。

  • 無參數
//調用方 只傳一個方法名
this.$store.commit('changeName')
//接收方 默認第一個參數是state,無參接收
 changeName(state) {
            state.name = '張韶涵'
            }
  • 載荷提交,只能提交一個參數
//調用方,第一個參數:方法名,第二個參數:參數
this.$store.commit('changeName',this.msg)
//接收方
 changeName(state, name) {
                    state.name = name ? name : '張韶涵';
                }
  • 載荷對象提交
//調用方,傳遞一個對象
               this.$store.commit('changeName',{
                   name:this.msg
               })
//接收方
                changeName(state, payload) {
                    state.name = payload.name ;
                    state.sex = payload.sex//給state新增一個屬性
                }
  • 純對象風格提交 type值是方法名
//提交一個純對象當做參數,type值為方法名
                    this.$store.commit({
                        type: 'changeName',
                        name: this.msg,
                        sex: '男'
                    })
//接收方
                changeName(state, payload) {
                    state.name = payload.name ;
                    state.sex = payload.sex//給state新增一個屬性
                }
  • 案例
<body>
    <div id="app">
        <!-- 組件AAA和組件BBB共同操作$store.state中的數據 -->
        <!-- 比我們之前學的組件之間通訊更加方便 -->
        <AAA></AAA>
        <BBB></BBB>
    </div>
    <script>
        /**
        *  mutation是更改store中狀態的唯一方法
        *  vuex中規定只能通過提交mutation的方式去更改store中的狀態
        *  store.commit()更改數據
        */
        let store = new Vuex.Store({
            state: {
                name: '鄧紫棋'
            },

            /**
            *   mutations對象中自定義方法來操作state中的數據
            *   并且每個方法會接受 state 作為第一個參數
            *   注意:Store對象中寫mutations;Mutation 必須是同步函數
            */
            mutations: {
                //不接收參數
                changeName(state) {
                    state.name = '張韶涵'
                },
                //只接收一個參數
                changeName(state, name) {
                    state.name = name ? name : '張韶涵';
                },
                //接收參數對象
                changeName(state, payload) {
                    state.name = payload.name ? payload.name : '張韶涵';
                    state.sex = payload.sex//給state新增一個屬性
                }
            }
        })

        //創建兩個組件
        const AAA = Vue.component('aaa', {
            template: `
                <div>
                    <!-- 4.使用$store.state中的數據 -->
                    <h1>{{this.$store.state.name}}</h1>
                    <h2>{{this.$store.state.sex}}</h2>
                </div>
            `
        })
        const BBB = Vue.component('bbb', {
            template: `
                <div>
                    <input type="text" placeholder="請輸入姓名" v-model='msg'>
                    <input type="button" value="確定" @click='change'>
                </div>
            `,
            data() {
                return {
                    msg: ''
                }
            },
            methods: {
                change() {
                    //1.無參數
                    // this.$store.commit('changeName')

                    //2.載荷提交,只能提交一個參數
                    // this.$store.commit('changeName',this.msg)

                    //3.載荷對象提交
                    // this.$store.commit('changeName',{
                    //     name:this.msg
                    // })

                    //4.純對象風格提交 type值是方法名
                    this.$store.commit({
                        type: 'changeName',
                        name: this.msg,
                        sex: '男'
                    })
                }
            }
        })
        let vm = new Vue({
            el: '#app',
            //把vue和store進行關聯
            store
        })
    </script>
</body>
組件通過mutation修改共享數據
Action

mutation中規則上是不允許異步操作的,于是vuex為我們提供了action。anctions對象中自定義方法來操作mutations,并且每個方法會接受 context 作為第一個參數,context對象與store對象具有相同的方法和屬性;action 與 mutation 除了使用了異步操作和調用mutation,其它使用并無差別 ;

  • 異步更新數據
                    //action事件的觸發同樣可以使用載荷和對象兩種方式,其它方式就不寫了和mutations方式一樣
                    this.$store.dispatch({
                        type:'changeNameAsync',//Store.anctions中的方法名
                        name: this.msg,
                        sex: '男'
                    })
 actions: {
                //接收數據 延遲一秒提交數據
                changeNameAsync(context, payload) {
                    //異步操作
                    setTimeout(() => {
                        context.commit('changeName',payload)
                    }, 1000)
                }
            }
            mutations: {
                //接收參數對象
                changeName(state, payload) {
                    state.name = payload.name ;
                    state.sex = payload.sex//給state新增一個屬性
                }
            }
  • 案例
<body>
    <div id="app">
        <AAA></AAA>
        <BBB></BBB>
    </div>
    <script>
        /**
        *  anction--異步更改狀態
        *  mutation中規則上是不允許異步操作的,于是vuex為我們提供了action。
        *  store.dispatch() 方法觸發
        */
        let store = new Vuex.Store({
            state: {
                name: '鄧紫棋'
            },

            /**
            *   mutations只能同步執行
            */
            mutations: {
                //接收參數對象
                changeName(state, payload) {
                    state.name = payload.name ? payload.name : '張韶涵';
                    state.sex = payload.sex//給state新增一個屬性
                }
            },
            /**
            *   anctions對象中自定義方法來操作mutations,并且每個方法會接受 context 作為第一個參數;
            *   context對象與store對象具有相同的方法和屬性
            *   action 與 mutation 除了使用了異步操作和調用mutation,其它使用并無差別 
            */
            actions: {
                //接收數據
                changeNameAsync(context, payload) {
                    //異步操作
                    setTimeout(() => {
                        context.commit({
                            type: 'changeName',
                            name: payload.name,
                            sex: '男'
                        })
                    }, 1000)
                }
            }
        })

        //創建兩個組件
        const AAA = Vue.component('aaa', {
            template: `
                <div>
                    <!-- 4.使用$store.state中的數據 -->
                    <h1>{{this.$store.state.name}}</h1>
                    <h2>{{this.$store.state.sex}}</h2>
                </div>
            `
        })
        const BBB = Vue.component('bbb', {
            template: `
                <div>
                    <input type="text" placeholder="請輸入姓名" v-model='msg'>
                    <input type="button" value="確定" @click='change'>
                </div>
            `,
            data() {
                return {
                    msg: ''
                }
            },
            methods: {
                change() {
                    //action事件的觸發同樣可以使用載荷和對象兩種方式,其它方式就不寫了和mutations方式一樣
                    this.$store.dispatch({
                        type:'changeNameAsync',//Store.anctions中的方法名
                        name: this.msg
                    })
                }
            }
        })
        let vm = new Vue({
            el: '#app',
            store
        })
    </script>
</body>
action延遲提交數據
getter

getters類似Vue實例中的計算屬性,當綁定的屬性發生變化后才會重新計算;每個方法都默認接收state參數。

  • getters使用
//在getters下創建一個getName方法,默認接收state,此方法和計算屬性用法一樣,當state中的name發生改變時會重新計算這個方法return結果
            getters:{
                getName(state){
                    let myName='';
                    if(state.name === '彭俊山'){
                        myName = '你是最帥的!'
                    }
                    return state.name + myName;
                }
            }
//在A組件中使用getters下的getName屬性,當B組件修改了state中的name后A組件中h2數據也會變化
<h2>{{this.$store.getters.getName}}</h2>
  • 案例
<body>
    <div id="app">
        <AAA></AAA>
        <BBB></BBB>
    </div>
    <script>
        let store = new Vuex.Store({
            state: {
                name: '鄧紫棋'
            },
            mutations: {
                //接收參數對象
                changeName(state, payload) {
                    state.name = payload.name ? payload.name : '張韶涵';
                }
            },
            /**
            *   getters類似Vue實例中的計算屬性,當綁定的屬性發生變化后才會重新計算
            *   每個方法都默認接收state參數
            */
            getters:{
                getName(state){
                    let myName='';
                    if(state.name === '彭俊山'){
                        myName = '你是最帥的!'
                    }
                    return state.name + myName;
                }
            }
        })

        //創建兩個組件
        const AAA = Vue.component('aaa', {
            template: `
                <div>
                    <!-- 使用$store.state中的數據 -->
                    <h1>{{this.$store.state.name}}</h1>
                    <!-- 使用$store.getters中的屬性 -->
                    <h2>{{this.$store.getters.getName}}</h2>
                </div>
            `
        })
        const BBB = Vue.component('bbb', {
            template: `
                <div>
                    <input type="text" placeholder="請輸入姓名" v-model='msg'>
                    <input type="button" value="確定" @click='change'>
                </div>
            `,
            data() {
                return {
                    msg: ''
                }
            },
            methods: {
                change() {
                    //純對象風格提交 type值是方法名
                    this.$store.commit({
                        type: 'changeName',
                        name: this.msg
                    })
                }
            }
        })
        let vm = new Vue({
            el: '#app',
            store
        })
    </script>
</body>
使用getters接收數據
vuex刷新頁面store數據丟失

當刷新頁面后,store中的數據都會丟失;將store的數據存儲在storage里,由于vue多為單頁面應用,且每次重新打開頁面需要保持數據為空 所以這里我們不選用localstorage,用sessionStorage會話機制;

            created() {
                //在頁面加載時讀取sessionStorage里的狀態信息
                if (sessionStorage.getItem("store")) {
                    this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem("store"))))
                }

                //在頁面刷新時將vuex里的信息保存到sessionStorage里
                window.addEventListener("beforeunload", () => {
                    sessionStorage.setItem("store", JSON.stringify(this.$store.state))
                })
            }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內容