Vue基礎(chǔ)

相關(guān)概念

混合開(kāi)發(fā)和前后端分離

  • 混合開(kāi)發(fā)(服務(wù)器端渲染)

  • 前后端分離
    后端提供接口,前端開(kāi)發(fā)界面效果(專(zhuān)注于用戶(hù)的交互)

庫(kù)和框架

  • 庫(kù)

    庫(kù)提供大量API甜孤,需要自己調(diào)用這些API簡(jiǎn)化開(kāi)發(fā)老速。

  • 框架

    框架提供了一些基礎(chǔ)服務(wù)粥喜,一般不需要自己調(diào)用,會(huì)自動(dòng)完成一些基本功能橘券。

什么是Vue

什么是Vue

  • 一款非常優(yōu)秀的前端 JavaScript 框架额湘,由尤雨溪?jiǎng)?chuàng)建開(kāi)發(fā)

  • 可以輕松構(gòu)建單頁(yè) (SPA) 應(yīng)用程序

  • 通過(guò) 指令 擴(kuò)展了 HTML,通過(guò) 表達(dá)式 綁定數(shù)據(jù)到 HTML

  • 最大程度上解放了 DOM 操作

  • 它能讓你更加的享受編程的樂(lè)趣

  • 數(shù)據(jù)驅(qū)動(dòng)旁舰,開(kāi)源

    官網(wǎng)

Vue的特點(diǎn)

  • 簡(jiǎn)單易用
  • 靈活漸進(jìn)式
  • 輕量高效
  • 虛擬 DOM
  • MVVM
  • 組件化

Vue初體驗(yàn)

安裝Vue

下載Vue

  • Vue.js 不支持 IE8 及其以下版本

  • 最新穩(wěn)定版本:2.5.16

  • 直接下載

  • CDN

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    
  • 使用 npm下載(默認(rèn)安裝最新穩(wěn)定版)

    npm install vue
    

Hello World

通過(guò)數(shù)據(jù)綁定的方式锋华,在界面上展示Hello World

<div id="app">
    <h1>{{ msg }}</h1>
</div>
<script src="vue.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            msg: 'Hello World'
        }
    });
</script>

Vue實(shí)例

創(chuàng)建Vue實(shí)例

每一個(gè)Vue應(yīng)用都是通過(guò)Vue構(gòu)造函數(shù)創(chuàng)建一個(gè)Vue的實(shí)例開(kāi)始

var vm = new Vue({
    // Vue的選項(xiàng)
});
  • Vue的選項(xiàng)
    • el 選項(xiàng):指定Vue作用的范圍
    • data 選項(xiàng):data提供數(shù)據(jù)對(duì)象,綁定的數(shù)據(jù)

模板語(yǔ)法

Vue.js 使用了基于 HTML 的模板語(yǔ)法箭窜,允許開(kāi)發(fā)者聲明式地將 DOM 綁定至底層 Vue 實(shí)例的數(shù)據(jù)毯焕。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循規(guī)范的瀏覽器和 HTML 解析器解析磺樱。

插值表達(dá)式

數(shù)據(jù)綁定最常見(jiàn)的形式就是使用“Mustache”語(yǔ)法 (雙大括號(hào)) 的文本插值:

<h1>
    {{ msg }}
</h1>

JavaScript表達(dá)式

對(duì)于所有的數(shù)據(jù)綁定纳猫,Vue.js 都提供了完全的 JavaScript 表達(dá)式支持。

{{ number + 1 }}

{{ age > 18 ? '年滿(mǎn)18歲' : '未滿(mǎn)18歲' }}

{{ message.split('').reverse().join('') }}

<h1>
    {{ msg }}
</h1>

注意:差值表達(dá)式中不能寫(xiě)語(yǔ)句竹捉。例如:var a = 10;

指令

指令 (Directives) 是帶有 v- 前綴的特殊特性续担。指令特性的值預(yù)期是單個(gè) JavaScript 表達(dá)式(v-for 是例外情況,稍后我們?cè)儆懻?活孩。指令的職責(zé)是,當(dāng)表達(dá)式的值改變時(shí)乖仇,將其產(chǎn)生的連帶影響憾儒,響應(yīng)式地作用于 DOM。參考文檔

v-html/v-text

  • v-text
    • v-text和差值表達(dá)式的區(qū)別
      • v-text 標(biāo)簽的指令更新整個(gè)標(biāo)簽中的內(nèi)容
      • 差值表達(dá)式乃沙,可以更新標(biāo)簽中局部的內(nèi)容
  • v-html
    • 可以渲染內(nèi)容中的HTML標(biāo)簽
    • 盡量避免使用起趾,否則會(huì)帶來(lái)危險(xiǎn)(XSS攻擊 跨站腳本攻擊)

v-bind

可以綁定標(biāo)簽上的任何屬性。

  • 動(dòng)態(tài)綁定圖片的路徑

    <img v-bind:src="src" />
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                src: '1.jpg'
            }
        });
    </script>
    
  • 綁定a標(biāo)簽上的id

    <a v-bind:href="'del.php?id=' + id">刪除</a>
    <script>
      var vm = new Vue({
            el: '#app',
            data: {
                id: 11
            }
        });
    </script>
    
  • 綁定class

    對(duì)象語(yǔ)法和數(shù)組語(yǔ)法

    • 對(duì)象語(yǔ)法

      如果isActive為true警儒,則返回的結(jié)果為 <div class="active"></div>

      <div v-bind:class="{active: isActive}">
          hei
      </div>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  isActive: true  
              }
          });
      </script>
      
    • 數(shù)組語(yǔ)法

      渲染的結(jié)果 <div class="active text-danger"></div>

      <div v-bind:class="[activeClass, dangerClass]">
          hei
      </div>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  activeClass: 'active',
                  dangerClass: 'text-danger'
              }
          });
      </script>
      
  • 綁定style

    對(duì)象語(yǔ)法和數(shù)組語(yǔ)法

    • 對(duì)象語(yǔ)法

      渲染的結(jié)果<div style="color: red; font-size: 18px;"></div>

      <div v-bind:style="{color: redColor, fontSize: font18 + 'px'}">
          hei
      </div>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  redColor: 'red',
                  font18: 18
              }
          });
      </script>
      
    • 數(shù)組語(yǔ)法

      <div v-bind:style="[color, fontSize]">abc</div>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  color: {
                      color: 'red'
                  },
                  fontSize: {
                      'font-size': '18px'
                  }
              }
          });
      </script>
      
  • 簡(jiǎn)化語(yǔ)法

    <div v-bind:class="{active: isActive}">
    </div>
    <!-- 可以簡(jiǎn)化為训裆,簡(jiǎn)化語(yǔ)法更常用 -->
    <div :class="{active: isActive}">
    </div>
    

v-model

表單元素的綁定

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

    • 數(shù)據(jù)發(fā)生變化可以更新到界面
    • 通過(guò)界面可以更改數(shù)據(jù)
  • 綁定文本框

    當(dāng)文本框的值發(fā)生邊框后眶根,div中的內(nèi)容也會(huì)發(fā)生變化

    <input type="text" v-model="name">
    <div>{{ name }}</div>
    <script>
        var vm = new Vue({
           el: '#app',
            data: {
                name: ''
            }
        });
    </script>
    
  • 綁定多行文本框

    <textarea v-model="name"></textarea>
    <div>{{ name }}</div>
    

    注意:多行文本框中不能使用{{ name }}的方式綁定

  • 綁定復(fù)選框

    • 綁定一個(gè)復(fù)選框
    <input type="checkbox" v-model="checked">
    <div>{{ checked }}</div>
    
    • 綁定多個(gè)復(fù)選框

      此種方式需要input標(biāo)簽提供value屬性

    吃飯:<input type="checkbox" value="eat" v-model="checklist"><br>
    睡覺(jué):<input type="checkbox" value="sleep" v-model="checklist"><br>
    打豆豆:<input type="checkbox" value="ddd" v-model="checklist"><br>
    {{ checklist }}
    <script>
        var vm = new Vue({
           el: '#app',
            data: {
                checklist: []
            }
        });
    </script>
    
  • 綁定單選框

    男<input type="radio" name="sex" value="男" v-model="sex">
    女<input type="radio" name="sex" value="女" v-model="sex">
    {{sex}}
    <script>
        var vm = new Vue({
           el: '#app',
            data: {
                sex: ''
            }
        });
    </script>
    
  • 綁定下拉框

    <div id="example-5">
      <select v-model="selected">
        <option disabled value="">請(qǐng)選擇</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <span>Selected: {{ selected }}</span>
    </div>
    

v-on

  • 綁定事件

  • 事件修飾符:

    • .prevent
    • .once
  • 簡(jiǎn)化語(yǔ)法

    <a href="#" @click.prevent="handleDelete">刪除<a>
    

v-show

v-if

v-for

v-cloak

v-once

  • 一次性綁定

Vue的選項(xiàng)對(duì)象

當(dāng)創(chuàng)建一個(gè) Vue 實(shí)例時(shí),你可以傳入一個(gè)選項(xiàng)對(duì)象边琉。你可以在 API 文檔 中瀏覽完整的選項(xiàng)列表属百。

  • el 選項(xiàng)

    參考文檔:https://cn.vuejs.org/v2/api/#el

    提供一個(gè)在頁(yè)面上已存在的 DOM 元素作為 Vue 實(shí)例的掛載目標(biāo)”湟蹋可以是 CSS 選擇器族扰,也可以是一個(gè) HTMLElement 實(shí)例。

    注意:

    • 不能作用到 <html> 或者 <body>
    • 也可以通過(guò) 實(shí)例.$mount() 手動(dòng)掛載
  • data 選項(xiàng)

    參考文檔:https://cn.vuejs.org/v2/api/#data

    • Vue 實(shí)例的數(shù)據(jù)對(duì)象定欧,能夠響應(yīng)式數(shù)據(jù)變化(雙向綁定)
    • 可以通過(guò) vm.$data 訪(fǎng)問(wèn)原始數(shù)據(jù)對(duì)象
    • Vue 實(shí)例也代理了 data 對(duì)象上所有的屬性渔呵,因此訪(fǎng)問(wèn) vm.a 等價(jià)于訪(fǎng)問(wèn) vm.$data.a
    • 視圖中綁定的數(shù)據(jù)必須顯式的初始化到 data 中
  • methods 選項(xiàng)

    參考文檔:https://cn.vuejs.org/v2/api/#methods

    methods 將被混入到 Vue 實(shí)例中】仇可以直接通過(guò) vm 實(shí)例訪(fǎng)問(wèn)這些方法扩氢,或者在指令表達(dá)式中使用。方法中的 this自動(dòng)綁定為 Vue 實(shí)例爷辱。

    注意: 不應(yīng)該使用箭頭函數(shù)來(lái)定義 method 函數(shù) (例如 plus: () => this.a++)录豺。理由是箭頭函數(shù)綁定了父級(jí)作用域的上下文,所以 this 將不會(huì)按照期望指向 Vue 實(shí)例托嚣,this.a 將是 undefined巩检。

    var vm = new Vue({
      data: { a: 1 },
      methods: {
        plus: function () {
          this.a++
        }
      }
    })
    vm.plus()
    vm.a // 2
    

案例:表格操作

  • 展示列表數(shù)據(jù)
  • 刪除數(shù)據(jù)
  • 添加數(shù)據(jù)

總結(jié):

  • Vue 最大程度上減少了頁(yè)面上的 DOM 操作
  • 讓開(kāi)發(fā)人員更專(zhuān)注于業(yè)務(wù)操作
  • 通過(guò)簡(jiǎn)潔的指令結(jié)合頁(yè)面結(jié)構(gòu)與邏輯數(shù)據(jù)
  • 代碼結(jié)構(gòu)更合理
  • 維護(hù)成本更低
  • 數(shù)據(jù)驅(qū)動(dòng)
  • VueJS 解放了傳統(tǒng) JavaScript 中頻繁的 DOM 操作

DevTools

https://github.com/vuejs/vue-devtools

MVVM

MVVMPattern.png

其它知識(shí)點(diǎn)

過(guò)濾器

Vue.js 允許你自定義過(guò)濾器,可被用于一些常見(jiàn)的文本格式化示启。過(guò)濾器可以用在兩個(gè)地方:雙花括號(hào)插值和 v-bind 表達(dá)式 (后者從 2.1.0+ 開(kāi)始支持)兢哭。

需求:對(duì)表格案例中的日期進(jìn)行格式化。

<td>{{ item.date | fmrTime('YYYY-MM-DD HH:mm:ss') }}</td>
<script>
Vue.filter('fmrTime', function (time, formatStr) {
    // 使用moment.js對(duì)日期進(jìn)行格式化
    return moment(time).format(formatStr);
});
</script>

計(jì)算屬性

模板內(nèi)的表達(dá)式非常便利夫嗓,但是設(shè)計(jì)它們的初衷是用于簡(jiǎn)單運(yùn)算的迟螺。

  • 計(jì)算屬性當(dāng)依賴(lài)的data中的數(shù)據(jù)發(fā)生變化的時(shí)候執(zhí)行

  • 計(jì)算屬性是基于它們的依賴(lài)進(jìn)行緩存的,計(jì)算屬性只有在它的相關(guān)依賴(lài)發(fā)生改變時(shí)才會(huì)重新求值舍咖。

    參考文檔

通過(guò)獲取時(shí)間矩父,演示計(jì)算屬性和methods中方法的區(qū)別(緩存數(shù)據(jù)的差異)。

計(jì)算屬性和方法的區(qū)別

  1. 方法每次調(diào)用都會(huì)執(zhí)行
  2. 計(jì)算屬性只有當(dāng)依賴(lài)的數(shù)據(jù)方法變化才會(huì)執(zhí)行

需求:表格案例中實(shí)現(xiàn)搜索功能

<tr v-for="(item, index) in newList" :key="index">
....
<tr v-if="newList.length === 0">
<script>
    var vm = new Vue({
        el: ....
        computed: {
            newList() {
              return this.list.filter((item) => {
                return item.name.startsWith(this.searchKey);
              });
            }
          }
    })
</script>

ref

在Vue.js中操作DOM排霉。

需求:表格案例中讓文本框默認(rèn)獲得焦窍株。

  1. 給要獲取焦點(diǎn)的元素增加ref屬性
  2. 在mounted中通過(guò)$refs獲取DOM元素
<input type="text" ref="username" v-model="name">

<script>
    var vm = new Vue({
       el: '#app',
       // mounted當(dāng)頁(yè)面加載完畢執(zhí)行
       mounted: function () {
           this.$refs.username.focus();
       },
       data.....,
    });
</script>

注意:Vue.js中不推薦直接操作DOM,除非必須否則不建議這么使用攻柠。

自定義指令

除了核心功能默認(rèn)的指令球订,例如:v-modelv-show,Vue 也允許注冊(cè)自定義指令瑰钮。

需求:表格案例中讓文本框默認(rèn)獲得焦冒滩。 給文本框增加自定義指令 v-focus

<input type="text" v-focus v-model="name">
<script>
// 全局自定義指令
Vue.directive('focus', {
    inserted: function (el) {
        el.focus();
    }
});
</script>

發(fā)送網(wǎng)絡(luò)請(qǐng)求

在Vue.js中發(fā)送網(wǎng)絡(luò)請(qǐng)求本質(zhì)還是ajax,我們可以使用插件方便操作浪谴。

  • vue-resource

    Vuejs的插件开睡,已經(jīng)不維護(hù)因苹,作者不推薦使用

  • axios

    可以在任何地方使用,推薦

axios

既可以在瀏覽器端又可以在node.js中使用的發(fā)送http請(qǐng)求的庫(kù)篇恒,支持Promise扶檐,默認(rèn)不支持jsonp。官網(wǎng)

  • 發(fā)送get請(qǐng)求

    axios.get('http://localhost:3000/brands')
          .then(res => {
            console.log(res.data);
          })
          .catch(err => {
            console.dir(err)
          });
    
  • 發(fā)送delete請(qǐng)求

    axios.delete('http://localhost:3000/brands/109')
          .then(res => {
            console.log(res.data);
          })
          .catch(err => {
            console.dir(err)
          });
    
  • 發(fā)送post請(qǐng)求

    axios.post('http://localhost:3000/brands', {name: '小米', date: new Date()})
          .then(res => {
            console.log(res);
          })
          .catch(err => {
            console.dir(err)
          });
    
  • jsonp

    https://github.com/axios/axios/blob/master/COOKBOOK.md

    jsonp('http://localhost:3000/brands', (err, data) => {
          if (err) {
            console.dir(err.msg);
          } else {
            console.dir(data);
          }
        });
    

表格案例

  • 數(shù)據(jù)列表

  • 刪除數(shù)據(jù)

  • 添加數(shù)據(jù)

  • 查詢(xún)數(shù)據(jù)

    • 偵聽(tīng)器

      監(jiān)聽(tīng)data對(duì)象的searchKey屬性的變化婚度,執(zhí)行相應(yīng)的操作

    watch: {
        searchKey: function (newValue, oldValue) {
            // 發(fā)送請(qǐng)求獲取列表數(shù)據(jù)
            axios.get('http://localhost:3000/brands?name_like=' + newValue)
                .then(res => {
                this.list = res.data;
            })
                .catch(err => {
                console.log(err);
            });
        }
    

過(guò)渡和動(dòng)畫(huà)

Vue 在插入蘸秘、更新或者移除 DOM 時(shí),提供多種不同方式的應(yīng)用過(guò)渡效果蝗茁。

在 CSS 過(guò)渡和動(dòng)畫(huà)中自動(dòng)應(yīng)用 class

Vue 提供了 transition 的封裝組件醋虏,在下列情形中,可以給任何元素和組件添加進(jìn)入/離開(kāi)過(guò)渡

// v要替換成transition組件的name屬性值
v-enter:定義進(jìn)入過(guò)渡的開(kāi)始狀態(tài)哮翘。
v-enter-active:定義進(jìn)入過(guò)渡生效時(shí)的狀態(tài)颈嚼。
v-enter-to: 2.1.8版及以上 定義進(jìn)入過(guò)渡的結(jié)束狀態(tài)。
v-leave: 定義離開(kāi)過(guò)渡的開(kāi)始狀態(tài)饭寺。
v-leave-active:定義離開(kāi)過(guò)渡生效時(shí)的狀態(tài)阻课。
v-leave-to: 2.1.8版及以上 定義離開(kāi)過(guò)渡的結(jié)束狀態(tài)。

示例:

<style>
    .box {
        position: absolute;
        left: 0;
        top: 50px;
        width: 100px;
        height: 100px;
        background-color: red;
    }
    .slide-enter, .slide-leave-to {
        left: 200px;
        opacity: 0;
    }
    .slide-enter-active, .slide-leave-active {
        transition: all 2s;
    }
    .slide-enter-to, .slide-leave {
        left: 0px;
        opacity: 1;
    }
</style>
<button @click="isShow = !isShow">顯示/隱藏</button>

<transition name="slide"> 
    <div v-show="isShow" class="box"></div>
</transition>
<script>
    var vm = new Vue({
      el: '#app',
      data: {
        isShow: true
      }
    });
</script>

自定義過(guò)渡動(dòng)畫(huà)的類(lèi)名

可以通過(guò)transition組件自定義過(guò)渡動(dòng)畫(huà)的類(lèi)名艰匙,可以方便結(jié)合第三方的動(dòng)畫(huà)庫(kù)使用限煞,比如:animate.css

// transition組件的屬性 
enter-class
enter-active-class
enter-to-class (2.1.8+)
leave-class
leave-active-class
leave-to-class (2.1.8+)

示例:


<button @click="isShow = !isShow">toggle</button>
<transition 
            enter-active-class="animated fadeIn"
            leave-active-class="animated fadeOut">
    <div v-show="isShow">hello</div>
</transition>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            isShow: true
        }
    });
</script>

組件

什么是組件

組件系統(tǒng)是 Vue 的另一個(gè)重要概念,因?yàn)樗且环N抽象员凝,允許我們使用小型署驻、獨(dú)立和通常可復(fù)用的組件構(gòu)建大型應(yīng)用健霹。仔細(xì)想想旺上,幾乎任意類(lèi)型的應(yīng)用界面都可以抽象為一個(gè)組件樹(shù):

components.png

組件和模塊

  • 模塊:側(cè)重于功能或者數(shù)據(jù)的封裝
  • 組件:包含了 template、style 和 script糖埋,而它的 script 可以由各種模塊組成
b25efd3e8af188b5ab36ccb66baddd71_hd.jpg

Vue中的組件開(kāi)發(fā)

組件是可復(fù)用的 Vue 實(shí)例宣吱,且?guī)в幸粋€(gè)名字,比如 <my-breadcrumb>瞳别。把這個(gè)組件作為自定義元素來(lái)使用征候。組件的好處是寫(xiě)一次可以進(jìn)行任意次數(shù)的復(fù)用。

組件參考文檔

全局組件

Vue.component('my-breadcrumb', {
      template: `<div>
          <span>{{ level1 }}</span>
          <span>/</span>
          <span @click="t">{{ level2 }}</span>
        <div>`,
      data() {
        return {
          level1: '用戶(hù)管理1',
          level2: '用戶(hù)列表1'
        };
      },
      methods: {
        t() {
          alert('hello');
        }
      }
    });

注意:

  1. 組件的模板中必須有且只有一個(gè)根標(biāo)簽
  2. 組件是一個(gè)特殊的Vue實(shí)例
  3. 組件中的data是一個(gè)方法祟敛,目的是讓每一個(gè)組件維護(hù)一個(gè)自己的數(shù)據(jù)
  4. 組件有自己的作用域

私有組件

// 私有組件
var ComponentA = {
    template: '<div>{{ msg }}</div>',
    data() {
        return {
            msg: 'hello'
        };
    }
};
var vm = new Vue({
    el: '#app',
    components: {
        'component-a': ComponentA
    }
});

通過(guò)Props給子組件傳值

  1. 子組件可以通過(guò) props 選項(xiàng)接收一個(gè)一些值倍奢,通過(guò) props 傳遞的值變成了改組件的一個(gè)屬性。

    var ComponentA = {
        template: '<div>{{ title }}</div>',
        props: ['title'],
    };
    
  2. 當(dāng)然子組件具有 props 選項(xiàng)后垒棋,數(shù)據(jù)可以通過(guò)標(biāo)簽的自定義屬性傳遞給子組件

    <component-a :title="msg"></component-a>
    
  3. 在vue的實(shí)例中提供該屬性值

    var vm = new Vue({
        el: '#app',
        data: {
            msg: 'hello heima',
        },
        components: {
            'component-a': ComponentA
        }
    });
    

    ?

Vue實(shí)例的生命周期

  • 什么生命周期

    定義:生命周期是指vue實(shí)例或者組件從誕生到消亡經(jīng)歷的每一個(gè)階段,在這些階段的前后可以設(shè)置一些函數(shù)當(dāng)做事件來(lái)調(diào)用痪宰。

  • 參考

    生命周期

  • 生命周期中的鉤子函數(shù)

//創(chuàng)造vue實(shí)例之后運(yùn)行此函數(shù)叼架,vm中的data/methods中的成員不可用
beforeCreate: function () {
   console.log("beforeCreate")
}
//創(chuàng)造vue實(shí)例之后運(yùn)行此函數(shù)畔裕,vm中的data/methods屬性可用
created: function () {
  console.log("created")
}
//當(dāng)vue實(shí)例的el節(jié)點(diǎn)或組件掛載到頁(yè)面以前運(yùn)行次函數(shù)
beforeMount: function () {
    console.log("beforeMount")
}
//當(dāng)vue實(shí)例的el節(jié)點(diǎn)或組件掛載到頁(yè)面以后運(yùn)行次函數(shù)
mounted: function () {
    console.log("mounted")
}
//當(dāng)vue實(shí)例數(shù)據(jù)發(fā)生改變前觸發(fā)此函數(shù)
beforeUpdate: function () {
    console.log("beforeUpdate")
}
//當(dāng)vue實(shí)例數(shù)據(jù)發(fā)生改變后觸發(fā)此函數(shù)
updated: function () {
    console.log("updated")
}

前端路由

單頁(yè)應(yīng)用

  • 什么是單頁(yè)應(yīng)用

    單頁(yè)應(yīng)用(single page web application,SPA)乖订,是在一個(gè)頁(yè)面完成所有的業(yè)務(wù)功能扮饶,瀏覽器一開(kāi)始會(huì)加載必需的HTML、CSS和JavaScript乍构,之后所有的操作都在這張頁(yè)面完成甜无,這一切都由JavaScript來(lái)控制。

  • 單頁(yè)應(yīng)用優(yōu)缺點(diǎn)

    • 優(yōu)點(diǎn)
      • 操作體驗(yàn)流暢
      • 完全的前端組件化
    • 缺點(diǎn)
      • 首次加載大量資源(可以只加載所需部分)
      • 對(duì)搜索引擎不友好
      • 開(kāi)發(fā)難度相對(duì)較高
  • 單頁(yè)應(yīng)用的原理

    • Hash路由

      • 利用URL上的hash哥遮,當(dāng)hash改變不會(huì)引起頁(yè)面刷新岂丘,所以可以利用 hash 值來(lái)做單頁(yè)面應(yīng)用的路由,

        并且當(dāng) url 的 hash 發(fā)生變化的時(shí)候眠饮,可以觸發(fā)相應(yīng) hashchange 回調(diào)函數(shù)奥帘。

      • 模擬實(shí)現(xiàn)

      var app = document.getElementById('app');
      window.onhashchange = function () {
          var hash = location.hash.replace('#', '');
          switch (hash.toLowerCase()) {
              case '/': 
                  app.innerHTML = '首頁(yè)內(nèi)容';
                  break;
              case '/users':
                  app.innerHTML = '用戶(hù)管理內(nèi)容';
                  break;
                  ……
          }
      };
      
    • History路由

      • History 路由是基于 HTML5 規(guī)范,在 HTML5 規(guī)范中提供了 history.pushState || history.replaceState 來(lái)進(jìn)行路由控制仪召。

vue-router

快速體驗(yàn)

  1. 導(dǎo)入vue和vue-router

  2. 設(shè)置HTML中的內(nèi)容

    <!-- router-link 最終會(huì)被渲染成a標(biāo)簽寨蹋,to指定路由的跳轉(zhuǎn)地址 -->
    <router-link to="/users">用戶(hù)管理</router-link>
    
    <!-- 路由匹配到的組件將渲染在這里 -->
    <router-view></router-view>
    
  3. 創(chuàng)建組件

    // 創(chuàng)建組件
    // 組件可以放到單獨(dú)的js文件中
    var Home = {
        template: '<div>這是Home內(nèi)容</div>'
    };
    var Users = {
        template: '<div>這是用戶(hù)管理內(nèi)容</div>'
    };
    
  4. 配置路由規(guī)則

    // 配置路由規(guī)則
    var router = new VueRouter({
        routes: [
            { name: 'home', path: '/', component: Home },
            { name: 'users', path: '/users', component: Users }
        ]
    });
    
  5. 設(shè)置vue的路由選項(xiàng)

    var vm = new Vue({
        el: '#app',
        router
    });
    

動(dòng)態(tài)路由匹配

假設(shè)有一個(gè)用戶(hù)列表,想要?jiǎng)h除某一個(gè)用戶(hù)扔茅,需要獲取用戶(hù)的id傳入組件內(nèi)已旧,如何實(shí)現(xiàn)呢?

此時(shí)可以通過(guò)路由傳參來(lái)實(shí)現(xiàn)召娜,具體步驟如下:

  1. 路由規(guī)則中增加參數(shù)运褪,在path最后增加 :id

    { name: 'users', path: '/users/:id', component: Users },
    
  2. 通過(guò) <router-link> 傳參,在路徑上傳入具體的值

    <router-link to="/users/120">用戶(hù)管理</router-link>
    
  3. 在組件內(nèi)部可以使用萤晴,this.$route 獲取當(dāng)前路由對(duì)象

    var Users = {
        template: '<div>這是用戶(hù)管理內(nèi)容 {{ $route.params.id }}</div>',
        mounted() {
            console.log(this.$route.params.id);
        }
    };
    

webpack

webpack 是一個(gè)模塊打包器吐句。webpack 的主要目標(biāo)是將 JavaScript 文件打包在一起,打包后的文件用于在瀏覽器中使用。

參考網(wǎng)站: 中文參考網(wǎng)站 官網(wǎng)

安裝webpack

最新webpack版本4.x

  1. 本地安裝webpack
  2. 安裝webpack的命令行工具 webpack-cli
$ npm install webpack webpack-cli --save-dev

快速實(shí)踐

參考官網(wǎng)

  • 項(xiàng)目結(jié)構(gòu)店读,默認(rèn)的目錄和文件名稱(chēng)不可修改
  webpack-demo
  |- package.json
+ |- /dist
+ |- index.html
  |- /src
    |- index.js
  • 入口js文件嗦枢,默認(rèn)名稱(chēng)index.js

math.js

export default {
  add(a, b) {
    return a + b;
  },
  sub(a, b) {
    return a - b;
  }
};

index.js

import Math from './math';

var x = 5;
var y = 6;

console.log(Math.add(5, 6));
console.log(Math.sub(5, 6));
  • 運(yùn)行
$ npm webpack

配置文件 webpack.config.js

webpack4.x 以前,必須要有配置文件屯断。在 webpack 4.x 以后文虏,可以無(wú)須任何配置使用(),然而大多數(shù)項(xiàng)目會(huì)需要很復(fù)雜的設(shè)置殖演,這就是為什么 webpack 仍然要支持氧秘。

  • 使用步驟

    • 項(xiàng)目根目錄下,手動(dòng)新建webpack.config.js
    const path = require('path');
    module.exports = {
      // 配置入口文件
      entry: './src/index.js',
      // 配置打包的文件和路徑
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
      }
    };
    
    • 運(yùn)行命令
    $ npm webpack --config webpack.config.js
    

    注意:打包的文件名改變后趴久,要修改index.html的script標(biāo)簽引入的文件名

    <script src="bundle.js"></script>

  • NPM腳本

    輸入上面的命令太繁瑣丸相,可以直接在終端運(yùn)行 webpack,會(huì)默認(rèn)加載webpack.config.js配置文件彼棍。

    • 在package.json中新增
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "webpack"
      },
    
    • 終端輸入
    $ npm run build
    

webpack常用的Loader

webpack 最出色的功能之一就是灭忠,除了 JavaScript膳算,還可以通過(guò) loader 引入任何其他類(lèi)型的文件。webpack 可以把所有文件作為模塊弛作,動(dòng)態(tài)打包(dynamically bundle)所有依賴(lài)項(xiàng)涕蜂。

參考文檔

打包CSS

  • 安裝和配置 style-loadercss-loader

    • 安裝
    $ npm install --save-dev style-loader css-loader
    
    • 配置,在webpack.config.js中
      const path = require('path');
      module.exports = {
        entry: './src/index.js',
        output: {
          filename: 'bundle.js',
          path: path.resolve(__dirname, 'dist')
        },
    +   module: {
    +     rules: [
    +       {
    +         test: /\.css$/,
    +         use: [
    +           'style-loader',
    +           'css-loader'
    +         ]
    +       }
    +     ]
    +   }
      };
    
  • 在入口index.js中映琳,導(dǎo)入css模塊

    import './css/index.css';
    
  • 運(yùn)行webpack命令

    $ npm run build
    

打包less

  • 安裝和配置

    $ npm install less-loader less --save-dev
    
    {
        test: /\.less$/,
        use: [
            'style-loader',
            'css-loader',
            'less-loader'
        ]
    }
    
  • less

    @color: yellow;
    body {
        background-color: @color;
    }
    

打包sass

  • 安裝和配置

    $ npm install sass-loader node-sass --save-dev
    
    {
        test: /\.scss$/,
        use: [
           'style-loader',
           'css-loader',
           'sass-loader'
        ]
    }
    
  • scss

    $color: red;
    body {
        background-color: $color;
    }
    

加載圖片

使用 file-loader 可以加載圖片和字體

  • 安裝和配置

    $ npm install --save-dev file-loader
    
    {
      test: /\.(png|svg|jpg|gif)$/,
      use: [
          'file-loader'
      ]
    }
    

加載字體

  • 配置

    {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
           'file-loader'
        ]
    }
    

webpack常用插件

除了通過(guò)loader去處理不同的資源文件以外机隙,webpack還支持插件機(jī)制,通過(guò)插件可以完成更多的事情萨西。

HtmlWebpackPlugin

自動(dòng)生成index.html有鹿,并引入資源文件,還可以通過(guò)配置壓縮HTML原杂。

  • 安裝

    npm install --save-dev html-webpack-plugin
    
  • 配置

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    ......
    plugins: [
        new HtmlWebpackPlugin({
            // 文檔的標(biāo)題
            title: 'Output Management',
            // 生成的文檔文件名
            filename: 'index.html',
            // 模板文件
            template: 'index.html',
            minify: {
              collapseWhitespace: true
            }
        })
    ]
    ......
    

CleanWebpackPlugin

清空dist目錄印颤。

  • 安裝

    npm install clean-webpack-plugin --save-dev
    
  • 配置

    const CleanWebpackPlugin = require('clean-webpack-plugin');
    
    ……
    new CleanWebpackPlugin(['dist']),
    ……
    

使用source map

參考文檔

在webpack.config.js中添加

devtool: 'inline-source-map',

使用 webpack-dev-server

webpack-dev-server 為你提供了一個(gè)簡(jiǎn)單的 web 服務(wù)器,并且能夠?qū)崟r(shí)重新加載(live reloading)穿肄。讓我們?cè)O(shè)置以下:

$ npm install --save-dev webpack-dev-server

webpack.config.js

devServer: {
    contentBase: './dist'
},

package.json

"start": "webpack-dev-server --open"

啟用HMR

模塊熱替換(Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一年局。它允許在運(yùn)行時(shí)更新各種模塊,而無(wú)需進(jìn)行完全刷新咸产。

webpack.config.js

const webpack = require('webpack');

.......
devServer: {
    contentBase: './dist',
    hot: true
},
.......

.......
     new webpack.NamedModulesPlugin(),
     new webpack.HotModuleReplacementPlugin()
.......

綜合案例

單文件組件

可以通過(guò) .vue 文件封裝組件矢否,參考文檔

  • 處理 .vue 文件 — 使用 vue-loader

    vue-loader使用比較特殊,如下

    $ npm install vue-loader --save-dev
    $ npm install vue-template-compiler --save-dev
    
    // 配置插件
    
    // 配置loader
    {
        test: /\.vue$/,
        loader: 'vue-loader'
    }
    

案例演示

image-20180526145007221.png

搭建項(xiàng)目結(jié)構(gòu)

  • 新建項(xiàng)目

    • 初始化package.json
    # 注意項(xiàng)目名稱(chēng)不能有中文
    $ npm init -y
    
    • 拷貝 webpack.config.js 到根目錄
    • 拷貝依賴(lài)
    "devDependencies": {
        "clean-webpack-plugin": "^0.1.19",
        "css-loader": "^0.28.11",
        "file-loader": "^1.1.11",
        "html-minifier": "^3.5.16",
        "html-webpack-plugin": "^3.2.0",
        "less": "^3.0.4",
        "less-loader": "^4.1.0",
        "node-sass": "^4.9.0",
        "sass-loader": "^7.0.1",
        "style-loader": "^0.21.0",
        "url-loader": "^1.0.1",
        "vue-loader": "^15.2.0",
        "vue-template-compiler": "^2.5.16",
        "webpack": "^4.8.3",
        "webpack-cli": "^2.1.4",
        "webpack-dev-server": "^3.1.4"
      },
      "dependencies": {
        "vue": "^2.5.16"
      }
    
    • 安裝依賴(lài)
    $ npm install
    
    • 下載bootstrap3
    $ npm install bootstrap@3.3.7 --save
    
  • 項(xiàng)目結(jié)構(gòu)

    [圖片上傳失敗...(image-de211b-1527597271494)]

配置根組件

  • 從模板中復(fù)制自定義樣式 index.css 到assets/css目錄

  • 入口文件 src/index.js

    import Vue from 'vue';
    import App from './App.vue';
    
    // 導(dǎo)入bootstrap樣式
    import 'bootstrap/dist/css/bootstrap.css';
    // 導(dǎo)入自定義樣式
    import './assets/css/index.css';
    
    const vm = new Vue({
      el: '#app',
      render: c => c(App)
    });
    
  • 根組件 src/App.vue

    復(fù)制模板中index.html的內(nèi)容到App.vue中

  • 運(yùn)行測(cè)試

    $ npm start
    

提取子組件

  • 提取頭部組件 components/header.vue

  • 提取側(cè)邊欄組件 components/sidebar.vue

  • 提取英雄列表組件 views/hero-list.vue

  • 根組件 src/App.vue 中加載組件

    import Header from './components/header.vue';
    import Sidebar from './components/sidebar.vue';
    import Heroes from './views/heroes.vue';
    export default {
      components: {
        Header,
        Sidebar,
        Heroes
      }
    };
    
    <div>
        <Header></Header>
        <div class="container-fluid">
            <div class="row">
                <Sidebar></Sidebar>
                <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
                    <h2 class="sub-header">Hero List</h2>
                    <a class="btn btn-success" href="add.html">Add</a>
                    <div class="table-responsive">
                        <Heroes></Heroes>
                    </div>
                </div>
            </div>
        </div>
    </div>
    

使用 Vue-Router 實(shí)現(xiàn)頁(yè)面導(dǎo)航管理

Vue-Router 能幫我們實(shí)現(xiàn)點(diǎn)擊某個(gè)導(dǎo)航鏈接的時(shí)候動(dòng)態(tài)的展示一個(gè)組件

  • 安裝路由模塊

    $ npm install vue-router --save
    
  • 注冊(cè)路由插件

    在index.js中脑溢,加載路由插件

    import VueRouter from 'vue-router';
    // 注冊(cè)路由插件
    Vue.use(VueRouter);
    
  • 加載組件僵朗,配置路由規(guī)則

    index.js中

    // 加載組件
    import Heroes from './views/heroes/heroes.vue';
    import Weapons from './views/weapons.vue';
    import Equips from './views/equips.vue';
    // 配置路由規(guī)則
    const router = new VueRouter({
      routes: [
        // 設(shè)置根路徑跳轉(zhuǎn)到英雄管理界面
        {'name': 'home', path: '/', redirect: {name: 'heroes'}},
        {'name': 'heroes', path: '/heroes', component: Heroes},
        {'name': 'weapons', path: '/weapons', component: Weapons},
        {'name': 'equips', path: '/equips', component: Equips}
      ]
    });
    
    new Vue({
      el: '#app',
      render: c => c(App),
      // 設(shè)置路由
      router
    });
    
  • src/App.vue 組件中留路由出口(告訴路由往哪里渲染 path 匹配到的組件)

    <Sidebar></Sidebar>
    <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
        <router-view></router-view>
    </div>
    
  • 在側(cè)邊欄 src/components/sidebar.vue 組件中 增加兩個(gè)導(dǎo)航鏈接

    將激活-class-應(yīng)用在外層元素

    <ul class="nav nav-sidebar">
        <router-link to="/heroes" tag="li" active-class="active">
            <a>英雄列表</a>
        </router-link>
        <router-link to="/weapons" tag="li" active-class="active">
            <a>武器列表</a>
        </router-link>
        <router-link to="/equips" tag="li" active-class="active">
            <a>裝備列表</a>
        </router-link>
    </ul>
    

JSON Server

可以快速開(kāi)啟 REST API 測(cè)試服務(wù)器的工具命令行工具。官網(wǎng)

安裝

$ npm install json-server -g

使用

$ json-server --watch db.json

接口地址

  • 獲取英雄列表
  • 請(qǐng)求路徑:http://localhost:3000/heros
  • 請(qǐng)求方法:GET
  • 根據(jù)英雄id獲取一個(gè)英雄

    • 請(qǐng)求路徑:

      http://localhost:3000/heros/:id
      
      • :id 需要給定一個(gè)英雄的 id
    • 請(qǐng)求方法:GET

  • 添加英雄

    • 請(qǐng)求路徑:http://localhost:3000/heros
    • 請(qǐng)求方法:POST
    • 請(qǐng)求體:
    {
      name: '英雄名稱(chēng)',
      gender: '英雄性別'
    }
    
  • 刪除英雄

    • 請(qǐng)求路徑:

      http://localhost:3000/heros/:id
      
      • :id 需要給定一個(gè)英雄的 id
    • 請(qǐng)求方法:DELETE

  • 編輯英雄

    • 請(qǐng)求路徑:

      http://localhost:3000/heros/:id
      
      • :id 需要給定一個(gè)英雄的 id
    • 請(qǐng)求方法:PATCH

    • 請(qǐng)求體:

      {
        name: '英雄名稱(chēng)',
        gender: '英雄性別'
      }
      

實(shí)現(xiàn)項(xiàng)目功能

安裝 axios 到項(xiàng)目中

 $ npm install axios --save

英雄列表

JS

import axios from 'axios';
export default {
  data() {
    return {
      heroes: []
    };
  },
  mounted() {
    this.loadData();
  },
  methods: {
    async loadData() {
      const res = await axios.get('http://localhost:3000/heros');
      this.heroes = res.data;
    }
  }
};

HTML

<tr v-for="(item, index) in heroes" :key="item.id">
    <td>{{ index + 1 }}</td>
    <td>{{ item.name }}</td>
    <td>{{ item.gender }}</td>
    <td>
        <!-- <router-link :to="'/edit/' + item.id"></router-link> -->
        <a href="edit.html">edit</a>
        &nbsp;&nbsp;
        <a href="javascript:window.confirm('Are you sure?')">delete</a>
    </td>
</tr>

刪除英雄

HTML

<!-- prevent 修飾符屑彻,阻止后續(xù)內(nèi)容的執(zhí)行 -->
<a href="#" @click.prevent="handleClick(item.id)">delete</a>

JS

async handleClick(id) {
    const isConfirmed = confirm('確認(rèn)要?jiǎng)h除該英雄验庙?');
    if (!isConfirmed) {
        return;
    }
    const res = await axios.delete(`http://localhost:3000/heros/${id}`);
    if (res.status === 200) {
        this.loadData();
        alert('刪除成功');
    } else {
        alert('刪除失敗');
    }
}

添加英雄

路由

  • 新建 src/views/heroes/heroes-add.vue

  • 配置路由

    import HeroesAdd from '../views/heroes/heroes-add.vue';
    
    // 增加一個(gè)路由規(guī)則
    {'name': 'heroesadd', path: '/heroes/add', component: HeroesAdd}, 
    {'name': 'heroes', path: '/heroes', component: Heroes},
    
  • src/views/heroes/heroes.vue 中點(diǎn)擊添加按鈕

    <router-link class="btn btn-success" to="/heroes/add">Add</router-link>
    

HTML

<h2 class="sub-header">添加英雄</h2>
<form>
    <div class="form-group">
        <label for="name">英雄名稱(chēng)</label>
        <input type="text" v-model="formData.name" class="form-control" id="name" placeholder="英雄名稱(chēng)">
    </div>
    <div class="form-group">
        <label for="sex">英雄性別</label>
        <input type="text" v-model="formData.gender" class="form-control" id="sex" placeholder="英雄性別">
    </div>
    <button type="submit" @click.prevent="handleAdd" class="btn btn-success">Submit</button>
</form>

JS

import axios from 'axios';

export default {
  data() {
    return {
      formData: {
        name: '',
        gender: ''
      }
    };
  },
  methods: {
    async handleAdd() {
      const res = await axios.post('http://localhost:3000/heros', this.formData);
      if (res.status === 201) {
        // 跳轉(zhuǎn)到列表頁(yè)面
        this.$router.push({
          name: 'heroes'
        });
      } else {
        alert('添加失敗');
      }
    }
  }
};

編輯英雄

路由

  • 新建 src/views/heroes/heroes-edit.vue

  • 配置路由

    import HeroesEdit from '../views/heroes/heroes-edit.vue';
    
    // 增加一個(gè)路由規(guī)則
    {'name': 'heroes', path: '/heroes', component: Heroes},
    {'name': 'heroesadd', path: '/heroes/add', component: HeroesAdd},
    {'name': 'heroesedit', path: '/heroes/edit/:id', component: HeroesEdit},
    
  • src/views/heroes/heroes.vue 中,設(shè)置編輯

    <router-link :to="{name: 'heroesedit', params: {id: item.id}}">edit</router-link>
    

HTML

和添加英雄一樣

JS

import axios from 'axios';

export default {
  data() {
    return {
      formData: {
        name: '',
        gender: ''
      },
      heroId: -1
    };
  },
  created() {
    this.heroId = this.$route.params.id;
    this.getHeroById();
  },
  methods: {
    // 根據(jù)id社牲,獲取英雄信息
    async getHeroById() {
      const res = await axios.get(`http://localhost:3000/heros/${this.heroId}`);
      if (res.status === 200) {
        this.formData = res.data;
      }
    },
    // 更新英雄信息
    async handleEdit() {
      const res = await axios.patch(`http://localhost:3000/heros/${this.heroId}`, this.formData);
      if (res.status === 200) {
        // 跳轉(zhuǎn)到列表頁(yè)面
        this.$router.push({
          name: 'heroes'
        });
      } else {
        alert('編輯失敗');
      }
    }
  }
};

NPM 緩存安裝

需要曾經(jīng)從網(wǎng)絡(luò)使用NPM安裝過(guò)想要的包

$ npm --cache-min 9999999 install webpack --save-dev
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末粪薛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子搏恤,更是在濱河造成了極大的恐慌违寿,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熟空,死亡現(xiàn)場(chǎng)離奇詭異藤巢,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)息罗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)掂咒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事绍刮∶庸ぃ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵录淡,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我油坝,道長(zhǎng)嫉戚,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任澈圈,我火速辦了婚禮彬檀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞬女。我一直安慰自己窍帝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布诽偷。 她就那樣靜靜地躺著坤学,像睡著了一般。 火紅的嫁衣襯著肌膚如雪报慕。 梳的紋絲不亂的頭發(fā)上深浮,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音眠冈,去河邊找鬼飞苇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蜗顽,可吹牛的內(nèi)容都是我干的布卡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼雇盖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼忿等!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起刊懈,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤这弧,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后虚汛,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體匾浪,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年卷哩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛋辈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖冷溶,靈堂內(nèi)的尸體忽然破棺而出渐白,到底是詐尸還是另有隱情,我是刑警寧澤逞频,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布纯衍,位于F島的核電站,受9級(jí)特大地震影響苗胀,放射性物質(zhì)發(fā)生泄漏襟诸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一基协、第九天 我趴在偏房一處隱蔽的房頂上張望歌亲。 院中可真熱鬧,春花似錦澜驮、人聲如沸陷揪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)悍缠。三九已至,卻和暖如春亭畜,著一層夾襖步出監(jiān)牢的瞬間扮休,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工拴鸵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玷坠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓劲藐,卻偏偏與公主長(zhǎng)得像八堡,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子聘芜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容