[超詳細(xì)] vue入門(mén)項(xiàng)目 TodoMVC 實(shí)現(xiàn)和思考

我的 github 項(xiàng)目地址:https://github.com/Nicklaus6/todomvc-vue

如果對(duì)你有幫助希望可以點(diǎn)個(gè) star 哦 ~

一扑毡、項(xiàng)目初始化

1.下載模板

在存放該項(xiàng)目的目錄下執(zhí)行:

git clone  https://github.com/tastejs/todomvc-app-template.git

2. 安裝依賴

進(jìn)入項(xiàng)目目錄

cd todomvc-vue

在項(xiàng)目目錄下安裝依賴

yarn

3. 引入vue

安裝vue

yarn add vue

index.html 中引入 vue

<script src="node_modules/vue/dist/vue.js"></script>

app.js中創(chuàng)建vue對(duì)象

(function (Vue) {
    window.app = new Vue({
        el:"#todoapp",
    })
})(Vue)

并在index.html中將其掛載到 DOM 元素 (#todoapp)

<section class="todoapp" id="todoapp">...</section>

完成以上操作后,用瀏覽器打開(kāi) index.html 婚温,若界面是以下這樣就說(shuō)明項(xiàng)目 初始化成功 了。

二揖膜、功能實(shí)現(xiàn)和思考

1. 列表數(shù)據(jù)渲染

  • 創(chuàng)建數(shù)據(jù)并加入Vue實(shí)例中的 data 對(duì)象
let todos = [
    // 先寫(xiě)兩條假數(shù)據(jù)測(cè)試一下
    { id: 1, content: "阿巴阿巴", completed: true },
    { id: 2, content: "馬卡馬卡", completed: false }
]

window.app = new Vue({
    data () {
      return {
        todos: todos
      }
    },
  })
  • 無(wú)數(shù)據(jù)時(shí)

    .main.footer 隱藏 : v-if 條件渲染

    <section class="main" v-if="todos.length">...</section>
    
    <section class="footer" v-if="todos.length">...</section>
    

思考:為什么這里使用 v-if 而不是 v-show 呢吼肥?他們的區(qū)別是跷敬?

共同點(diǎn) : 他們的功能都是 條件渲染

不同點(diǎn) : v-show 的原理是修改 css 的display屬性柒爸,并沒(méi)有操作 dom元素准浴。

? v-if 的原理是根據(jù)條件,動(dòng)態(tài)地銷(xiāo)毀或添加 dom元素捎稚。但 v-if 也是 惰性

? 的乐横,如果初始條件為 false ,則什么都不做今野,等到條件為 true 了再開(kāi)始渲染葡公。

因此v-if 有更高的切換開(kāi)銷(xiāo)条霜,而 v-show 有更高的初始渲染開(kāi)銷(xiāo)催什。如果需要頻繁切換,建議使用 v-show宰睡,如果不需要頻繁切換蒲凶,則可以使用 v-if 。而這里.main.footer并不會(huì)頻繁切換狀態(tài)拆内,所以使用 v-if豹爹。

?

  • 有數(shù)據(jù)時(shí)

    • 動(dòng)態(tài)渲染數(shù)據(jù)列表 : v-for 列表渲染

    • 綁定相應(yīng)狀態(tài)下的 class : :class class 的綁定

    • checkbox 選中狀態(tài)切換 : v-model 雙向數(shù)據(jù)綁定

    • label 內(nèi)容渲染 : Mustache 語(yǔ)法

    <ul class="todo-list">
            <li v-for="(item,index) in todos"
                :key="item.id"
                :class="{completed:item.completed}">
              <div class="view">
                <input class="toggle"
                       type="checkbox"
                       v-model="item.completed">
                <label>{{ item.content }}</label>
                <button class="destroy"></button>
              </div>
              <input class="edit" value="Create a TodoMVC template">
            </li>
    </ul>
    

    思考 :

    1. 為什么在使用 v-for 時(shí) 還要使用 :key

      Vue在更新使用 v-for 渲染的列表元素時(shí)矛纹,會(huì)采用一種 就地復(fù)用 策略臂聋,盡可能的嘗試就地修改/復(fù)用相同類(lèi)型元素。而 :key 給了每個(gè)節(jié)點(diǎn)一個(gè) 唯一標(biāo)識(shí),讓虛擬 DOM 中的 Diff 算法正確識(shí)別節(jié)點(diǎn)孩等,從而重用和重新排序現(xiàn)有元素艾君,從而更加 高效地更新虛擬 DOM

  1. v-model 的原理肄方?

    v-model 用于表單數(shù)據(jù)的雙向綁定冰垄,本質(zhì)上是語(yǔ)法糖。

    它背后做了兩個(gè)操作 :

    v-bind 綁定一個(gè) value 屬性权她,v-on 給當(dāng)前元素綁定 input 事件虹茶。

    <input v-model="something"></input>
    以上操作等價(jià)于
    <input :value="something" @input="something = $event.target.value"></input>
    先綁定一個(gè) something 屬性,在通過(guò)監(jiān)聽(tīng) input 事件隅要,當(dāng)用戶改變輸入框數(shù)據(jù)時(shí)蝴罪,通過(guò)設(shè)置當(dāng)前事件的目標(biāo)dom的value,從而實(shí)現(xiàn)雙向數(shù)據(jù)綁定的效果步清。
    

2. 添加新的 todo

  • 按下回車(chē)要门,輸入內(nèi)容不為空,添加一條 todo :

    • @keyup.enter 監(jiān)聽(tīng)鍵盤(pán)回車(chē)事件并在 vue 的 methods中添加相應(yīng)方法
    • 內(nèi)容為空則什么都不做
    • 添加完后輸入框內(nèi)容清空
    <input class="new-todo"
           placeholder="What needs to be done?"
           autofocus
           @keyup.enter="addTodo">
    </input>
    
    methods: {
          addTodo ($event) {
            // 創(chuàng)建 newTodo 對(duì)象廓啊,獲取數(shù)據(jù)
            const newTodo = {
              id: this.todos.length + 1,
              content: $event.target.value.trim(),
              completed: false
            }
            // 如果內(nèi)容為空欢搜,什么都不做
            if (!newTodo.content.length) return
            // 如果內(nèi)容不為空,將 newTodo 加入 todos 中
            this.todos.push(newTodo)
            // 清空輸入框內(nèi)容
            $event.target.value = ''
          }
        }
    

3. 刪除 todo

  • 點(diǎn)擊 .destroy谴轮,刪除所在的 todo :

    • @click 監(jiān)聽(tīng)按鈕點(diǎn)擊事件并在 vue 的 methods中添加相應(yīng)方法

    • 數(shù)組的 splice 方法刪除 todo

      <button class="destroy" @click="destroyTodo(index)"></button>
      
      methods: {
            destroyTodo (index) {
              // 用 splice 方法通過(guò)參數(shù) index 來(lái)找到要?jiǎng)h除的 todo炒瘟,刪除一項(xiàng)
              this.todos.splice(index, 1)
            }
      }
      

?

4. 編輯 todo

  • 雙擊 label ,進(jìn)入編輯模式

    • @dblclick 監(jiān)聽(tīng) label 雙擊事件

    • :class 給所在的 li綁定 class .editing

    這里設(shè)置一個(gè)中間變量 currentEditing (就像一種狀態(tài))第步,當(dāng)監(jiān)聽(tīng)到 label 雙擊事件時(shí)唧领,currentEditing = item,而當(dāng) item === currentEditing 時(shí)雌续,就給所在的 li綁定 class

    <li v-for="(item,index) in todos" :key="item.id"
        :class="{ completed: item.completed , editing: item === currentEditing }">
    </li>
    
    <label @dblclick="currentEditing = item">{{ item.content }}</label>
    
    • 局部自定義指令 directives 讓輸入框自動(dòng)獲取焦點(diǎn)

      <input class="edit" 
             :value="item.content"
             v-editing-focus="item === currentEditing">
      </input>
      
      directives:{
          // update 在所有組件的 VNode(虛擬節(jié)點(diǎn)) 更新時(shí)調(diào)用斩个,但可能發(fā)生在其子 VNode 更新之前。
          update(el,binding){
            // el : 用來(lái)操作元素 DOM
            // binding.value : 指令的綁定值 這里即 item === currentEditing
              if(binding.value){
                  el.focus()
              }
          }
        }
      

      ?

  • 輸入內(nèi)容后回車(chē)或失焦驯杜,將原本的 todo內(nèi)容替換為輸入的內(nèi)容
    • @keyup.enter 監(jiān)聽(tīng)鍵盤(pán)回車(chē)事件受啥;@blur 監(jiān)聽(tīng)失焦事件

      <input class="edit"
             :value="item.content"
             v-editing-focus="item === currentEditing"
             @keyup.enter="saveEditing(item,index,$event)"                                          @blur="saveEditing(item,index,$event)">
      
  • 在vue 的 methods中添加相應(yīng)方法

    saveEditing (item, index, $event) {
            // 將輸入的內(nèi)容保存到 newContent 變量中
            const newContent = $event.target.value.trim()
            // 如果內(nèi)容為空 就刪除 todo 
            if (!newContent) this.destroyTodo(index)
            //將原本容替換為輸入的內(nèi)容
            item.content = newContent
            //通過(guò)設(shè)置 currentEditing ,移除掉 .editing 鸽心,退出編輯模式滚局。
            this.currentEditing = null
          }
    
  • :valueinput綁定內(nèi)容

    <input class="toggle"
           type="checkbox"
           v-model="item.completed"
           :value="item.content">
    
  • 按下 esc,退出編輯模式
  • @keyup.esc 監(jiān)聽(tīng)鍵盤(pán)回車(chē)事件

    <input class="edit"
           :value="item.content"
           v-editing-focus="item === currentEditing"
           @keyup.enter="saveEditing(item,index,$event)"                                          @blur="saveEditing(item,index,$event)"
           @keyup.esc="quitEditing">
    
  • 并在vue 的 methods中添加相應(yīng)方法

    quitEditing () {
            // 通過(guò)設(shè)置 currentEditing 移除掉 .editing 退出編輯模式
            this.currentEditing = null
          }
    

5. 標(biāo)記所有任務(wù)完成或者未完成

  • 點(diǎn)擊 .toggle-all 顽频,將所有的 todos 的完成狀態(tài) 和 .toggleAll 的勾選狀態(tài) 綁定

    • @click 監(jiān)聽(tīng)按鈕點(diǎn)擊事件

      <input id="toggle-all" class="toggle-all" type="checkbox"
             @click="toggleAll">
      
    • 并在 vue 的 methods中添加相應(yīng)方法

      methods: {
            toggleAll ($event) {
              // 獲取 .toggleAll 的勾選狀態(tài)
              let isToggled = $event.target.checked
              // 將所有的 todos 的完成狀態(tài) 和 .toggleAll 的勾選狀態(tài) 綁定
              this.todos.forEach(item => item.completed = isToggled);
            },        
      }
      
  • .toggleAll 的勾選狀態(tài) 和 todos 是否全選綁定

    • .toggle-allchecked 屬性綁定一個(gè)的計(jì)算屬性來(lái)監(jiān)聽(tīng)單選框選中情況的改變

      <input id="toggle-all" class="toggle-all" type="checkbox"
             @click="toggleAll"
             :checked="isAllChecked">
      <!-- 也可以寫(xiě) v-model="isAllChecked" 因?yàn)?checkbox 使用 checked property 和 change 事件 -->
      
    • 并在 vue 的 computed中添加計(jì)算屬性

      computed: {
            isAllChecked () {
              return !this.todos.find(item => !item.completed)
            }
          },
      

思考:

  1. computed vs methods ? computed vs watch ?

    computed vs methods

    計(jì)算屬性是基于它們的響應(yīng)式依賴進(jìn)行緩存的藤肢。只有相關(guān)響應(yīng)式依賴發(fā)生改變時(shí),他們才會(huì)重新求值糯景。而方法會(huì)在每次重新渲染時(shí)調(diào)用函數(shù)嘁圈,不占用緩存但是會(huì)消耗一定時(shí)間省骂。

    computed vs watch

    雖然計(jì)算屬性在大多數(shù)情況下更合適,但是當(dāng)需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷(xiāo)較大的操作時(shí)最住,使用偵聽(tīng)器更合適钞澳。

  1. v-model 在內(nèi)部為 checkbox 使用的 property`和拋出的事件?

    checkbox 和 radio 使用 checked property 和 change 事件涨缚。什么是 change 事件轧粟?其實(shí)就是 HTML 的 onchange 事件。它是元素值被改變(用戶改變脓魏,用代碼內(nèi)部改變無(wú)效)且表單失焦時(shí)觸發(fā)的事件兰吟。

    所以此時(shí) v-model的原理是:

    <input type="checkbox" v-model="something"></input>
    以上操作等價(jià)于
    <input type="checkbox" 
           :checked="something" @change="something = $event.target.checked">
    </input>
    

    同理,select 字段將 value 作為 prop 并將 change 作為事件茂翔。

    <select name="" id="" v-model="something">
                <option disabled value="">請(qǐng)選擇</option>
                <option>A</option>
                <option>B</option>
    </select>
    以上操作等價(jià)于
    <select name="" id="" :value="something" @change="something = $event.target.value">
                <option disabled value="">請(qǐng)選擇</option>
                <option>A</option>
                <option>B</option>
    </select>
    

6. 計(jì)數(shù)

  • .todo-count顯示未完成的 todo 的數(shù)量

    • 模板語(yǔ)法

       <span class="todo-count"><strong>{{todoCount}}</strong> item left</span>
      
  • 在 vue 中添加計(jì)算屬性

    computed: {
          todoCount () {
            // es6 的 filter 方法
            return this.todos.filter(item => !item.completed).length
          }
        },
    

7. 清除所有完成項(xiàng)

  • 點(diǎn)擊 clear-completed 混蔼,清除所有完成項(xiàng)

    • @click 監(jiān)聽(tīng)按鈕點(diǎn)擊事件并在 vue 中添加相應(yīng)方法

      <button class="clear-completed" @click="clearCompleted">Clear completed</button>
      
      methods: {
            clearCompleted () {
              this.todos = this.todos.filter(item => !item.completed)
            }
          },
      
  • 當(dāng)至少有一項(xiàng)完成項(xiàng)才顯示

    • v-show 切換狀態(tài)

      <button class="clear-completed" 
              @click="clearCompleted"
              v-show="hasCompleted">Clear completed</button>
      
  • 綁定計(jì)算屬性判斷是否至少有一項(xiàng)完成項(xiàng)

    computed: {
          hasCompleted () {
            // 當(dāng)至少有一項(xiàng)完成項(xiàng)才顯示
            return this.todos.filter(item => item.completed > 0).length > 0
          }
        },
    

8. 三種狀態(tài)數(shù)據(jù)過(guò)濾

  • 點(diǎn)擊不同的狀態(tài),獲取相應(yīng)的數(shù)據(jù)

    • 在 vue 的 data 中保存過(guò)濾狀態(tài)檩电,默認(rèn)為 'all'

      data () {
            return {
              todos: todos,
              currentEditing: null,
              filterState: 'all'
            }
          },
      
  • 通過(guò) window.onhashchange 獲取點(diǎn)擊狀態(tài)的路由 hash 保存為當(dāng)前的狀態(tài)值,并且賦給 data 中的過(guò)濾狀態(tài)

    // 路由狀態(tài)切換
      // 當(dāng) 一個(gè)窗口的 hash (URL 中 # 后面的部分)改變時(shí)就會(huì)觸發(fā) hashchange 事件
      window.onhashchange = function () {
        // 獲取當(dāng)前點(diǎn)擊狀態(tài)的路由 hash  獲取的 location.hash 是 #/all 這樣的數(shù)據(jù)
        const hash = window.location.hash.substr(2) || 'all'
        // 將路由狀態(tài)賦給 過(guò)濾狀態(tài)
        window.app.filterState = hash
      }
      // 頁(yè)面第一次進(jìn)來(lái)保持狀態(tài)
      window.onhashchange()
    
  • 通過(guò)計(jì)算屬性來(lái)渲染過(guò)濾狀態(tài)下的渲染的數(shù)據(jù)

    定義計(jì)算屬性:根據(jù)過(guò)濾狀態(tài)返回相應(yīng)的todo

    computed: {
          filterTodos () {
            switch (this.filterState) {
              case 'active':
                return this.todos.filter(item => !item.completed);
                break
              case 'completed':
                return this.todos.filter(item => item.completed);
                break
              default:
                return this.todos;
                break
            }
          }
        },
    

    修改 todo 的列表循環(huán)

    <li v-for="(item,index) in filterTodos" :key="item.id"
        :class="{
                completed: item.completed,
                editing: item === currentEditing
        }">
    </li>
    
  • 根據(jù)狀態(tài)改變狀態(tài)按鈕的樣式

    • :class 給選中的狀態(tài)綁定 .selected 樣式

      <ul class="filters">
              <li>
                <a :class="{selected:filterState==='all'}" href="#/">All</a>
              </li>
              <li>
                <a href="#/active"
                   :class="{selected:filterState==='active'}">Active</a>
              </li>
              <li>
                <a href="#/completed"
                   :class="{selected:filterState==='completed'}">Completed</a>
              </li>
            </ul>
      

9. 數(shù)據(jù)持久化

  • 在 vue 實(shí)例外部 定義一個(gè)數(shù)據(jù)存儲(chǔ)對(duì)象, 有以下兩個(gè)方法:

    • 獲取本地?cái)?shù)據(jù)
    • 保存數(shù)據(jù)到本地
      let STOREAGE_KEY = "todo-items"
    
      // 定義數(shù)據(jù)存儲(chǔ)對(duì)象
      const todoStorage = {
        // 獲取本地?cái)?shù)據(jù) localStorage.getItem("key")
        fetch: function () {
          // 返回獲取的本地?cái)?shù)據(jù)的數(shù)組對(duì)象 ,如果為空府树,則是空數(shù)組 || '[]',
          return JSON.parse(localStorage.getItem(STOREAGE_KEY) || '[]')
        },
        // 保存數(shù)據(jù)到本地 localStorage.setItem("key","value")
        save: function (todos) {
          // 以 JSON 字符串形式存儲(chǔ) todos 數(shù)據(jù)
          localStorage.setItem(STOREAGE_KEY, JSON.stringify(todos))
        }
      }
    
  • 修改 vue 實(shí)例的 data 中的 todos俐末,以本地?cái)?shù)據(jù)初始化

    data () {
          return {
            todos: todoStorage.fetch(),
            currentEditing: null,
            filterState: 'all'
          }
    
  • 通過(guò) vue 的 watch 監(jiān)聽(tīng) todos的變化,一有改變就將數(shù)據(jù)保存到本地

    watch: {
          // 監(jiān)聽(tīng) todos 變化
          todos: {
            deep: true, // 監(jiān)聽(tīng)對(duì)象內(nèi)部值的變化
            handler (newTodos) {
              todoStorage.save(newTodos)
            }
          }
        },
    

思考: 為什么使用 localStorage 而不是 sessionStorage奄侠?

localStorage 用于 長(zhǎng)久 保存整個(gè)網(wǎng)站的數(shù)據(jù)卓箫,關(guān)閉標(biāo)簽頁(yè)數(shù)據(jù)也不會(huì)消失,保存的數(shù)據(jù)沒(méi)有過(guò)期時(shí)間垄潮,直到手動(dòng)刪除烹卒。

localStorage的語(yǔ)法:

  • 保存數(shù)據(jù)

    localStorage.setItem("key","value")
    
  • 讀取數(shù)據(jù)

    let myLocalStorage = localStorage.getItem("key")
    
  • 刪除數(shù)據(jù)

    localStorage.removeItem("key")
    

sessionStorage 用于只想將數(shù)據(jù)保存在 當(dāng)前會(huì)話 中時(shí),關(guān)閉標(biāo)簽頁(yè)數(shù)據(jù)會(huì)被刪除弯洗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旅急,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子牡整,更是在濱河造成了極大的恐慌藐吮,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逃贝,死亡現(xiàn)場(chǎng)離奇詭異谣辞,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)沐扳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)泥从,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人沪摄,你說(shuō)我怎么就攤上這事躯嫉∩春妫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵和敬,是天一觀的道長(zhǎng)凹炸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)昼弟,這世上最難降的妖魔是什么啤它? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮舱痘,結(jié)果婚禮上变骡,老公的妹妹穿的比我還像新娘。我一直安慰自己芭逝,他們只是感情好塌碌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著旬盯,像睡著了一般台妆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胖翰,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天接剩,我揣著相機(jī)與錄音,去河邊找鬼萨咳。 笑死懊缺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的培他。 我是一名探鬼主播鹃两,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼舀凛!你這毒婦竟也來(lái)了俊扳?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猛遍,失蹤者是張志新(化名)和其女友劉穎拣度,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體螃壤,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抗果,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奸晴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冤馏。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寄啼,靈堂內(nèi)的尸體忽然破棺而出逮光,到底是詐尸還是另有隱情代箭,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布涕刚,位于F島的核電站嗡综,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杜漠。R本人自食惡果不足惜极景,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驾茴。 院中可真熱鬧盼樟,春花似錦、人聲如沸锈至。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)峡捡。三九已至击碗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間们拙,已是汗流浹背稍途。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睛竣,地道東北人晰房。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓求摇,卻偏偏與公主長(zhǎng)得像射沟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子与境,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354