老司機讀書筆記——Vue學習筆記

Vue學習筆記

這篇文章你將看到以下內容:

  • 一個iOS開發視角學習Vue需要學習的一些知識點

Vue實例結構

var vm = new Vue({
  //樣式表名
  el: '#example',
  //屬性
  data: {
    message: 'Hello'
  },
  //計算屬性
  computed: {
    fullName: {
        // getter
        get: function () {
            return this.firstName + ' ' + this.lastName
        },
        // setter
        set: function (newValue) {
            var names = newValue.split(' ')
            this.firstName = names[0]
            this.lastName = names[names.length - 1]
        }
    }
  },
  //屬性觀察
  watch: {
    // 如果 `question` 發生改變,這個函數就會運行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.getAnswer()
    }
  },
  //實例函數
  methods: {
    reversedMessage: function () {
        return this.message.split('').reverse().join('')
    }
  }
})

Vue監聽實例

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>

<!-- 因為 AJAX 庫和通用工具的生態已經相當豐富,Vue 核心代碼沒有重復 -->
<!-- 提供這些功能以保持精簡。這也可以讓你自由選擇自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 `question` 發生改變,這個函數就會運行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.getAnswer()
    }
  },
  methods: {
    // `_.debounce` 是一個通過 Lodash 限制操作頻率的函數。
    // 在這個例子中,我們希望限制訪問 yesno.wtf/api 的頻率
    // AJAX 請求直到用戶輸入完畢才會發出。想要了解更多關于
    // `_.debounce` 函數 (及其近親 `_.throttle`) 的知識,
    // 請參考:https://lodash.com/docs#debounce
    getAnswer: _.debounce(
      function () {
        if (this.question.indexOf('?') === -1) {
          this.answer = 'Questions usually contain a question mark. ;-)'
          return
        }
        this.answer = 'Thinking...'
        var vm = this
        axios.get('https://yesno.wtf/api')
          .then(function (response) {
            vm.answer = _.capitalize(response.data.answer)
          })
          .catch(function (error) {
            vm.answer = 'Error! Could not reach the API. ' + error
          })
      },
      // 這是我們為判定用戶停止輸入等待的毫秒數
      500
    )
  }
})
</script>

Vue實例生命周期

beforeCreate->created->beforeMount->mounted->beforeUpdate->updated->beforeDestroy->destryed


v-bind

綁定標簽字段與Vue對應關系

<!-- 完整語法 -->
<a v-bind:href="url">...</a>

<!-- 縮寫 -->
<a :href="url">...</a>

v-on

綁定事件與Vue對應關系

<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>

<!-- 縮寫 -->
<a @click="doSomething">...</a>

Vue組件

Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})

Class綁定

普通

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

數組

HTML:
<div v-bind:class="[activeClass, errorClass]"></div>

JS:
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

條件

<div v-bind:class="[{ active: isActive }, errorClass]"></div>

Style綁定

HTML:
<div v-bind:style="styleObject"></div>

JS:
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

v-if

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

關于是否顯示,v-show同樣可以達到相同效果,不同的是

v-show 的元素始終會被渲染并保留在 DOM 中。v-show 只是簡單地切換元素的 CSS 屬性 display。

注意,v-show 不支持 <template> 元素,也不支持 v-else。


v-if 與v-show

v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷毀和重建。

v-if 也是惰性的:如果在初始渲染時條件為假,則什么也不做——直到條件第一次變為真時,才會開始渲染條件塊。

相比之下,v-show 就簡單得多——不管初始條件是什么,元素總是會被渲染,并且只是簡單地基于 CSS 進行切換。

一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在運行時條件很少改變,則使用 v-if 較好。


v-for

HTML:
<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>

JS:
var example2 = new Vue({
  el: '#example-2',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

對于對象同樣可以使用v-for語法

HTML:
<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }}: {{ value }}
</div>

JS:
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    }
  }
})

當v-for配合v-if同時使用時,相當于在for循環中添加if判斷。

2.2.0+ 的版本里,當在組件中使用 v-for 時,key 現在是必須的。
eg.:

<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>

TODO LIST的完成例子

HTML:
<div id="todo-list-example">
  <input
    v-model="newTodoText"
    v-on:keyup.enter="addNewTodo"
    placeholder="Add a todo"
  >
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>

JS:
Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">X</button>\
    </li>\
  ',
  props: ['title']
})

new Vue({
  el: '#todo-list-example',
  data: {
    newTodoText: '',
    todos: [
      {
        id: 1,
        title: 'Do the dishes',
      },
      {
        id: 2,
        title: 'Take out the trash',
      },
      {
        id: 3,
        title: 'Mow the lawn'
      }
    ],
    nextTodoId: 4
  },
  methods: {
    addNewTodo: function () {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})


關于數組

Vue為數組提供了很多變異方法,一邊觀察數組的變化從而更新試圖:

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

同時,Vue也提供了一些非變異方法,他們不會改變原數組的值而是返回一個新的數組:

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

在使用上,我們可以用一個新數組替換舊數組,Vue內部做了優化,提高渲染效率。

值得注意的是,由于 JavaScript 的限制,Vue 不能檢測以下變動的數組:

當你利用索引直接設置一個項時,例如:vm.items[indexOfItem] = newValue
當你修改數組的長度時,例如:vm.items.length = newLength

應對第一種問題我們可以使用以下三種方式進行值得替換:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
// Vue.set的全局縮寫
vm.$set(vm.items, indexOfItem, newValue)

第二種問題解決方案:

vm.items.splice(newLength)

不僅是數組,對象同樣會有Vue檢測不到的變化:

Vue 不能檢測對象屬性的添加或刪除

為了解決這個問題我呢們可以調用以下函數:

添加

Vue.set(vm.userProfile, 'age', 27)
vm.$set(vm.userProfile, 'age', 27)

添加多個值時請使用新對象替換就對象的方式:

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

關于Vue中的事件綁定

v-on可以用于給事件綁定回調,回調可以是一個表達式:

HTML:
<div id="example-1">
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>

JS:
var example1 = new Vue({
  el: '#example-1',
  data: {
    counter: 0
  }
})

同樣可以是一個方法:

HTML:
<div id="example-2">
  <!-- `greet` 是在下面定義的方法名 -->
  <button v-on:click="greet">Greet</button>
</div>

JS:
var example2 = new Vue({
  el: '#example-2',
  data: {
    name: 'Vue.js'
  },
  // 在 `methods` 對象中定義方法
  methods: {
    greet: function (event) {
      // `this` 在方法里指向當前 Vue 實例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
})

另外,greet方法是可以以JS形勢直接調用的

example2.greet()

由于此種特性,事件綁定還有一種變形:

HTML:
<div id="example-3">
  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="say('what')">Say what</button>
</div>

JS:
new Vue({
  el: '#example-3',
  methods: {
    say: function (message) {
      alert(message)
    }
  }
})

此外,Vue為v-on提供了一系列事件修飾符,用來定制事件的傳遞

<!-- 阻止單擊事件繼續傳播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修飾符可以串聯 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件監聽器時使用事件捕獲模式 -->
<!-- 即元素自身觸發的事件先在此處處理,然后才交由內部元素進行處理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只當在 event.target 是當前元素自身時觸發處理函數 -->
<!-- 即事件不是從內部元素觸發的 -->
<div v-on:click.self="doThat">...</div>

<!-- 點擊事件將只會觸發一次 -->
<a v-on:click.once="doThis"></a>

<!-- 滾動事件的默認行為 (即滾動行為) 將會立即觸發 -->
<!-- 而不會等待 `onScroll` 完成  -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>

按鍵修飾符

  • .enter
  • .tab
  • .delete (捕獲“刪除”和“退格”鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
<!-- 同上 -->
<input v-on:keyup.enter="submit">

v-model

輸入框

HTML:
<div class="app-8">
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
  <textarea v-model="message" placeholder="add multiple lines"></textarea>
</div>

JS:
var app8 = new Vue({
  el: '.app-8',
  data: {
    message: 'Hello Vue!'
  }
})

復選框(單個):

HTML:
<div class = "app-9">
  <input type="checkbox" id="checkbox" v-model="checked">
  <label for="checkbox">{{ checked }}</label>
</div>

JS:
var app9 = new Vue({
  el: '.app-9',
  data: {
    checked: true
  }
})

復選框(多個):

HTML:
<div class='app-10'>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>

JS:
var app10 = new Vue({
  el: '.app-10',
  data: {
    checkedNames: []
  }
})

單選框:

HTML:
<div class="app-11">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>

JS:
var app11 = new Vue({
    el: '.app-11',
    data: {
        picked:""
    }
})

選擇框:

HTML:
<div id="app-12">
  <select v-model="selected">
    <option disabled value="">請選擇</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>

JS:
new Vue({
  el: '#app-12',
  data: {
    selected: ''
  }
})

如果 v-model 表達式的初始值未能匹配任何選項,<select> 元素將被渲染為“未選中”狀態。在 iOS 中,這會使用戶無法選擇第一個選項。因為這樣的情況下,iOS 不會觸發 change 事件。因此,更推薦像上面這樣提供一個值為空的禁用選項。

上述選擇也可以用v-for來動態創建

HTML:
<div class = "app-13">
  <select v-model="selected">
    <option v-for="option in options" v-bind:value="option.value">
      {{ option.text }}
    </option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>

JS:
new Vue({
  el: '.app-13',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})

動態綁定的value值:

<!-- 當選中時,`picked` 為字符串 "a" -->
<input type="radio" v-model="picked" value="a">

<!-- `toggle` 為 true 或 false -->
<input type="checkbox" v-model="toggle">

<!-- 當選中第一個選項時,`selected` 為字符串 "abc" -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

修飾符

.lazy

在默認情況下,v-model 在每次 input 事件觸發后將輸入框的值與數據進行同步 (除了上述輸入法組合文字時)。你可以添加 lazy 修飾符,從而轉變為使用 change 事件進行同步:

<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg" >

.number

如果想自動將用戶的輸入值轉為數值類型,可以給 v-model 添加 number 修飾符:

<input v-model.number="age" type="number">

這通常很有用,因為即使在 type="number" 時,HTML 輸入元素的值也總會返回字符串。

.trim

如果要自動過濾用戶輸入的首尾空白字符,可以給 v-model 添加 trim 修飾符:

<input v-model.trim="msg">

組件

Vue注冊全局組件


Vue.component('my-component', {
  // 選項
  template: '<div>A custom component!</div>'
})

組件在注冊之后,便可以作為自定義元素 <my-component></my-component> 在一個實例的模板中使用。注意確保在初始化根實例之前注冊組件:

HTML:
<div id="example">//(此處需要有根實例引用)
 <my-component></my-component>
</div>

JS:
// 注冊
Vue.component('my-component', {
 template: '<div>A custom component!</div>'
})

// 創建根實例(此處必須常見根實例,否則無法使用自定義組件)
new Vue({
 el: '#example'
})

局部注冊

你不必把每個組件都注冊到全局。你可以通過某個 Vue 實例/組件的實例選項 components 注冊僅在其作用域中可用的組件:

var Child = {
  template: '<div>A custom component!</div>'
}

new Vue({
  // ...
  components: {
    // <my-component> 將只在父組件模板中可用
    'my-component': Child
  }
})

data 必須是函數

構造 Vue 實例時傳入的各種選項大多數都可以在組件里使用。只有一個例外:data 必須是函數。

HTML:
<div id="example-2">
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</div>

JS:

Vue.component('simple-counter', {
  template: '<button v-on:click="counter += 1">{{ counter }}</button>',
  // 技術上 data 的確是一個函數了,因此 Vue 不會警告,
  // 但是我們卻給每個組件實例返回了同一個對象的引用
  data: function () {
    return { counter: 0 }
  }
})

new Vue({
  el: '#example-2'
})

使用Prop傳遞數據

組件實例的作用域是孤立的。這意味著不能 (也不應該) 在子組件的模板內直接引用父組件的數據。父組件的數據需要通過 prop 才能下發到子組件中。

子組件要顯式地用 props 選項聲明它預期的數據:

HTML:
<!-- HTML 特性是不區分大小寫的。所以,當使用的不是字符串模板時,camelCase (駝峰式命名) 的 prop 需要轉換為相對應的 kebab-case (短橫線分隔式命名) -->
<child my-message="hello!"></child>

JS:
Vue.component('child', {
  // 在 JavaScript 中使用 camelCase
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})
關于data與Prop

Prop更像是對外屬性,外界可以使用,而data中的字段只能作為私有屬性供組件自身使用。

動態Prop綁定

HTML:
<div id="prop-example-2">
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

JS:
new Vue({
  el: '#prop-example-2',
  data: {
    parentMsg: 'Message from parent'
  }
})

單向數據流

Prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,但是反過來不會。這是為了防止子組件無意間修改了父組件的狀態,來避免應用的數據流變得難以理解。

另外,每次父組件更新時,子組件的所有 prop 都會更新為最新值。這意味著你不應該在子組件內部改變 prop。如果你這么做了,Vue 會在控制臺給出警告。

在兩種情況下,我們很容易忍不住想去修改 prop 中數據:

  • Prop 作為初始值傳入后,子組件想把它當作局部數據來用;

  • Prop 作為原始數據傳入,由子組件處理成其它數據輸出。

對這兩種情況,正確的應對方式是:
1.定義一個局部變量,并用 prop 的值初始化它:

props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

2.定義一個計算屬性,處理 prop 的值并返回:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

注意在 JavaScript 中對象和數組是引用類型,指向同一個內存空間,如果 prop 是一個對象或數組,在子組件內部改變它會影響父組件的狀態。

Prop驗證

我們可以為組件的 prop 指定驗證規則。如果傳入的數據不符合要求,Vue 會發出警告。這對于開發給他人使用的組件非常有用。

要指定驗證規則,需要用對象的形式來定義 prop,而不能用字符串數組:

Vue.component('example', {
  props: {
    // 基礎類型檢測 (`null` 指允許任何類型)
    propA: Number,
    // 可能是多種類型
    propB: [String, Number],
    // 必傳且是字符串
    propC: {
      type: String,
      required: true
    },
    // 數值且有默認值
    propD: {
      type: Number,
      default: 100
    },
    // 數組/對象的默認值應當由一個工廠函數返回
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗證函數
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

type 可以是下面原生構造器:

  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array
  • Symbol

type 也可以是一個自定義構造器函數,使用 instanceof 檢測。

當 prop 驗證失敗,Vue 會拋出警告 (如果使用的是開發版本)。注意 prop 會在組件實例創建之前進行校驗,所以在 default 或 validator 函數里,諸如 data、computed 或 methods 等實例屬性還無法使用。


非Prop特性

盡管為組件定義明確的 prop 是推薦的傳參方式,組件的作者卻并不總能預見到組件被使用的場景。所以,組件可以接收任意傳入的特性,這些特性都會被添加到組件的根元素上。

<bs-date-input data-3d-date-picker="true"></bs-date-input>

添加屬性 data-3d-date-picker="true" 之后,它會被自動添加到 bs-date-input 的根元素上。


自定義事件

父控件通過Prop向子控件傳遞數據,那么子控件又如何與父控件通信呢?
我們可以通過父控件監聽子控件事件來實現這一需求,那么就要借助事件接口:

  • 使用 $on(eventName) 監聽事件
  • 使用 $emit(eventName, optionalPayload) 觸發事件

eg.:

HTML:

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

JS:
Vue.component('button-counter', {
  template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})

new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})

非父子組件間通信

事實上$emit和$on只是向我們提供了事件監聽的接口,并沒有將范圍限制在父子控件間,在簡單的場景下,可以使用一個空的 Vue 實例作為事件總線:

var bus = new Vue()
// 觸發組件 A 中的事件
bus.$emit('id-selected', 1)
// 在組件 B 創建的鉤子中監聽事件
bus.$on('id-selected', function (id) {
  // ...
})

好的,今天的內容就到這里了,有什么問題可以來老司機的個人博客、GitHub或者郵件我

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

推薦閱讀更多精彩內容