better-Bscroll

謝謝作者的文章? 非常喜歡? 請允許收藏隙笆!

博客園首頁博問閃存新隨筆訂閱管理


vue之better-scroll的封裝,包含下拉刷新,上拉加載功能及UI(核心為借鑒升筏,我僅僅是給輪子套上了外胎...)

先發(fā)原文作者撑柔、地址等信息。我把內(nèi)容全部搬過來了您访,也可以去看原文铅忿。內(nèi)容絕對是滿滿的干貨,給原作者點贊A橥簟(我添加的內(nèi)容在轉(zhuǎn)載過來的后面檀训,內(nèi)容不多)

作者: ustbhuangyi

鏈接:http://www.imooc.com/article/18232來源:慕課網(wǎng)

在我們?nèi)粘5囊苿佣隧椖块_發(fā)中,處理滾動列表是再常見不過的需求了享言,以滴滴為例峻凫,可以是這樣豎向滾動的列表,如圖所示:

也可以是橫向滾動的導航欄览露,如圖所示:

可以打開“微信 —> 錢包—>滴滴出行”體驗效果荧琼。

我們在實現(xiàn)這類滾動功能的時候,會用到我寫的第三方庫差牛,better-scroll命锄。

什么是 better-scroll

better-scroll 是一個移動端滾動的解決方案,它是基于 iscroll 的重寫多糠,它和 iscroll 的主要區(qū)別在這里累舷。better-scroll 也很強大,不僅可以做普通的滾動列表夹孔,還可以做輪播圖被盈、picker 等等析孽。

better-scroll 的滾動原理

不少同學可能用過 better-scroll,我收到反饋最多的問題是:

我的 better-scroll 初始化了只怎, 但是沒法滾動袜瞬。

不能滾動是現(xiàn)象,我們得搞清楚這其中的根本原因身堡。在這之前邓尤,我們先來看一下瀏覽器的滾動原理:

瀏覽器的滾動條大家都會遇到,當頁面內(nèi)容的高度超過視口高度的時候贴谎,會出現(xiàn)縱向滾動條汞扎;當頁面內(nèi)容的寬度超過視口寬度的時候,會出現(xiàn)橫向滾動條擅这。也就是當我們的視口展示不下內(nèi)容的時候澈魄,會通過滾動條的方式讓用戶滾動屏幕看到剩余的內(nèi)容。

那么對于 better-scroll 也是一樣的道理仲翎,我們先來看一下 better-scroll 常見的 html 結(jié)構(gòu):

  • ...
  • ...
  • ...

    為了更加直觀痹扇,我們再來看一張圖:

    綠色部分為 wrapper,也就是父容器溯香,它會有固定的高度鲫构。黃色部分為 content,它是父容器的第一個子元素玫坛,它的高度會隨著內(nèi)容的大小而撐高结笨。那么,當 content 的高度不超過父容器的高度湿镀,是不能滾動的禀梳,而它一旦超過了父容器的高度,我們就可以滾動內(nèi)容區(qū)了肠骆,這就是 better-scroll 的滾動原理算途。

    那么,我們怎么初始化 better-scroll 呢蚀腿,如果是上述 html 結(jié)構(gòu)嘴瓤,那么初始化代碼如下:

    import BScroll from 'better-scroll'let wrapper= document.querySelector('.wrapper')

    let scroll=newBScroll(wrapper, {})

    better-scroll 對外暴露了一個 BScroll 的類,我們初始化只需要 new 一個類的實例即可莉钙。第一個參數(shù)就是我們 wrapper 的 DOM 對象廓脆,第二個是一些配置參數(shù),具體參考better-scroll 的文檔磁玉。

    better-scroll 的初始化時機很重要停忿,因為它在初始化的時候,會計算父元素和子元素的高度和寬度蚊伞,來決定是否可以縱向和橫向滾動席赂。因此吮铭,我們在初始化它的時候,必須確保父元素和子元素的內(nèi)容已經(jīng)正確渲染了颅停。如果子元素或者父元素 DOM 結(jié)構(gòu)發(fā)生改變的時候谓晌,必須重新調(diào)用scroll.refresh()方法重新計算來確保滾動效果的正常。所以同學們反饋的 better-scroll 不能滾動的原因多半是初始化 better-scroll 的時機不對癞揉,或者是當 DOM 結(jié)構(gòu)發(fā)送變化的時候并沒有重新計算 better-scroll纸肉。

    better-scroll 遇見 Vue

    相信很多同學對Vue.js都不陌生,當 better-scroll 遇見 Vue喊熟,會擦出怎樣的火花呢柏肪?

    如何在 Vue 中使用 better-scroll

    很多同學開始接觸使用 better-scroll 都是受到了我的一門教學課程——《Vue.js高仿餓了么外賣App》的影響。在那門課程中芥牌,我們把 better-scroll 和 Vue 做了結(jié)合预吆,實現(xiàn)了很多列表滾動的效果。在 Vue 中的使用方法如下:

    ?

    ? ?
      ? ? ?
    • ...
    • ? ? ?
    • ...
    • ...
    ?
    import BScroll from'better-scroll'exportdefault{

    mounted() {this.$nextTick(() =>{this.scroll =newBscroll(this.$refs.wrapper, {})

    })

    }

    }

    Vue.js 提供了我們一個獲取 DOM 對象的接口——vm.$refs胳泉。在這里,我們通過了this.$refs.wrapper訪問到了這個 DOM 對象岩遗,并且我們在 mounted 這個鉤子函數(shù)里扇商,this.$nextTick的回調(diào)函數(shù)中初始化 better-scroll 。因為這個時候宿礁,wrapper 的 DOM 已經(jīng)渲染了案铺,我們可以正確計算它以及它內(nèi)層 content 的高度,以確保滾動正常梆靖。

    這里的this.$nextTick是一個異步函數(shù)控汉,為了確保 DOM 已經(jīng)渲染,感興趣的同學可以了解一下它的內(nèi)部實現(xiàn)細節(jié)返吻,底層用到了 MutationObserver 或者是setTimeout(fn, 0)姑子。其實我們在這里把this.$nextTick替換成setTimeout(fn, 20)也是可以的(20 ms 是一個經(jīng)驗值,每一個 Tick 約為 17 ms)测僵,對用戶體驗而言都是無感知的街佑。

    異步數(shù)據(jù)的處理

    在我們的實際工作中,列表的數(shù)據(jù)往往都是異步獲取的捍靠,因此我們初始化 better-scroll 的時機需要在數(shù)據(jù)獲取后沐旨,代碼如下:

    ?

    ? ?
      ? ? ?
    • {{item}}
    • ? ?
    ?
    import BScroll from'better-scroll'exportdefault{

    data() {return{

    data: []

    }

    },

    created() {

    requestData().then((res)=>{this.data =res.datathis.$nextTick(() =>{this.scroll =newBscroll(this.$refs.wrapper, {})

    })

    })

    }

    }

    這里的 requestData 是偽代碼,作用就是發(fā)起一個 http 請求從服務端獲取數(shù)據(jù)榨婆,并且這個函數(shù)返回的是一個 promise(實際項目中我們可能會用axios或者vue-resource)磁携。我們獲取到數(shù)據(jù)的后,需要通過異步的方式再去初始化 better-scroll良风,因為 Vue 是數(shù)據(jù)驅(qū)動的谊迄, Vue 數(shù)據(jù)發(fā)生變化(this.data = res.data)到頁面重新渲染是一個異步的過程闷供,我們的初始化時機是要在 DOM 重新渲染后,所以這里用到了this.$nextTick鳞上,當然替換成setTimeout(fn, 20)也是可以的这吻。

    為什么這里在 created 這個鉤子函數(shù)里請求數(shù)據(jù)而不是放到 mounted 的鉤子函數(shù)里?因為 requestData 是發(fā)送一個網(wǎng)絡請求篙议,這是一個異步過程唾糯,當拿到響應數(shù)據(jù)的時候,Vue 的 DOM 早就已經(jīng)渲染好了鬼贱,但是數(shù)據(jù)改變 —> DOM 重新渲染仍然是一個異步過程移怯,所以即使在我們拿到數(shù)據(jù)后,也要異步初始化 better-scroll这难。

    數(shù)據(jù)的動態(tài)更新

    我們在實際開發(fā)中舟误,除了數(shù)據(jù)異步獲取,還有一些場景可以動態(tài)更新列表中的數(shù)據(jù)姻乓,比如常見的下拉加載嵌溢,上拉刷新等。比如我們用 better-scroll 配合 Vue 實現(xiàn)下拉加載功能蹋岩,代碼如下:

    ?

    ? ?
      ? ? ?
    • {{item}}
    • ? ?
    ? ?
    ?
    import BScroll from'better-scroll'exportdefault{

    data() {return{

    data: []

    }

    },

    created() {this.loadData()

    },

    methods: {

    loadData() {

    requestData().then((res)=>{this.data = res.data.concat(this.data)this.$nextTick(() =>{if(!this.scroll) {this.scroll =newBscroll(this.$refs.wrapper, {})this.scroll.on('touchend', (pos) =>{//下拉動作if(pos.y > 50) {this.loadData()

    }

    })

    }else{this.scroll.refresh()

    }

    })

    })

    }

    }

    }

    這段代碼比之前稍微復雜一些, 當我們在滑動列表松開手指時候赖草, better-scroll 會對外派發(fā)一個 touchend 事件,我們監(jiān)聽了這個事件剪个,并且判斷了 pos.y > 50(我們把這個行為定義成一次下拉的動作)秧骑。如果是下拉的話我們會重新請求數(shù)據(jù),并且把新的數(shù)據(jù)和之前的 data 做一次 concat扣囊,也就更新了列表的數(shù)據(jù)乎折,那么數(shù)據(jù)的改變就會映射到 DOM 的變化。需要注意的一點侵歇,這里我們對this.scroll做了判斷骂澄,如果沒有初始化過我們會通過new BScroll初始化,并且綁定一些事件惕虑,否則我們會調(diào)用this.scroll.refresh方法重新計算酗洒,來確保滾動效果的正常。

    這里枷遂,我們就通過 better-scroll 配合 Vue樱衷,實現(xiàn)了列表的下拉刷新功能,上拉加載也是類似的套路酒唉,一切看上去都是 ok 的矩桂。但是,我們發(fā)現(xiàn)這里寫了大量命令式的代碼(這一點不是 Vue.js 推薦的),如果有很多類似滾動的組件侄榴,我們就需要寫很多類似的命令式且重復性的代碼雹锣,而且我們把數(shù)據(jù)請求和 better-scroll 也做了強耦合,這些對于一個追求編程逼格的人來說癞蚕,就不 ok 了蕊爵。

    scroll 組件的抽象和封裝

    因此,我們有強烈的需求抽象出來一個 scroll 組件桦山,類似小程序的 scroll-view 組件攒射,方便開發(fā)者的使用。

    首先恒水,我們要考慮的是 scroll 組件本質(zhì)上就是一個可以滾動的列表組件会放,至于列表的 DOM 結(jié)構(gòu),只需要滿足 better-scroll 的 DOM 結(jié)構(gòu)規(guī)范即可钉凌,具體用什么標簽咧最,有哪些輔助節(jié)點(比如下拉刷新上拉加載的 loading 層),這些都不是 scroll 組件需要關心的御雕。因此矢沿, scroll 組件的 DOM 結(jié)構(gòu)十分簡單,如下所示:

    這里我們用到了 Vue 的特殊元素—— slot 插槽酸纲,它可以滿足我們靈活定制列表 DOM 結(jié)構(gòu)的需求捣鲸。接下來我們來看看 JS 部分:

    import BScroll from'better-scroll'exportdefault{

    props: {/**

    * 1 滾動的時候會派發(fā)scroll事件,會截流福青。

    * 2 滾動的時候?qū)崟r派發(fā)scroll事件,不會截流脓诡。

    * 3 除了實時派發(fā)scroll事件无午,在swipe的情況下仍然能實時派發(fā)scroll事件*/probeType: {

    type: Number,default: 1},/**

    * 點擊列表是否派發(fā)click事件*/click: {

    type: Boolean,default:true},/**

    * 是否開啟橫向滾動*/scrollX: {

    type: Boolean,default:false},/**

    * 是否派發(fā)滾動事件*/listenScroll: {

    type: Boolean,default:false},/**

    * 列表的數(shù)據(jù)*/data: {

    type: Array,default:null},/**

    * 是否派發(fā)滾動到底部的事件,用于上拉加載*/pullup: {

    type: Boolean,default:false},/**

    * 是否派發(fā)頂部下拉的事件祝谚,用于下拉刷新*/pulldown: {

    type: Boolean,default:false},/**

    * 是否派發(fā)列表滾動開始的事件*/beforeScroll: {

    type: Boolean,default:false},/**

    * 當數(shù)據(jù)更新后宪迟,刷新scroll的延時。*/refreshDelay: {

    type: Number,default: 20}

    },

    mounted() {//保證在DOM渲染完畢后初始化better-scrollsetTimeout(() =>{this._initScroll()

    },20)

    },

    methods: {

    _initScroll() {if(!this.$refs.wrapper) {return}//better-scroll的初始化this.scroll =newBScroll(this.$refs.wrapper, {

    probeType:this.probeType,

    click:this.click,

    scrollX:this.scrollX

    })//是否派發(fā)滾動事件if(this.listenScroll) {

    let me=thisthis.scroll.on('scroll', (pos) =>{

    me.$emit('scroll', pos)

    })

    }//是否派發(fā)滾動到底部事件交惯,用于上拉加載if(this.pullup) {this.scroll.on('scrollEnd', () =>{//滾動到底部if(this.scroll.y <= (this.scroll.maxScrollY + 50)) {this.$emit('scrollToEnd')

    }

    })

    }//是否派發(fā)頂部下拉事件次泽,用于下拉刷新if(this.pulldown) {this.scroll.on('touchend', (pos) =>{//下拉動作if(pos.y > 50) {this.$emit('pulldown')

    }

    })

    }//是否派發(fā)列表滾動開始的事件if(this.beforeScroll) {this.scroll.on('beforeScrollStart', () =>{this.$emit('beforeScroll')

    })

    }

    },

    disable() {//代理better-scroll的disable方法this.scroll &&this.scroll.disable()

    },

    enable() {//代理better-scroll的enable方法this.scroll &&this.scroll.enable()},

    refresh(){//代理better-scroll的refresh方法this.scroll &&this.scroll.refresh()},scrollTo(){//代理better-scroll的scrollTo方法this.scroll &&this.scroll.scrollTo.apply(this.scroll, arguments)},scrollToElement(){//代理better-scroll的scrollToElement方法this.scroll &&this.scroll.scrollToElement.apply(this.scroll, arguments)}},watch:{//監(jiān)聽數(shù)據(jù)的變化,延時refreshDelay時間后調(diào)用refresh方法重新計算席爽,保證滾動效果正常data(){

    setTimeout(()=>{this.refresh()},this.refreshDelay)}}}

    JS 部分實際上就是對 better-scroll 做一層 Vue 的封裝意荤,通過 props 的形式,把一些對 better-scroll 定制化的控制權(quán)交給父組件只锻;通過 methods 暴露的一些方法對 better-scroll 的方法做一層代理玖像;通過 watch 傳入的 data,當 data 發(fā)生改變的時候齐饮,在適當?shù)臅r機調(diào)用 refresh 方法重新計算 better-scroll 確保滾動效果正常捐寥,這里之所以要有一個 refreshDelay 的設置是考慮到如果我們對列表操作用到了 transition-group 做動畫效果笤昨,那么 DOM 的渲染完畢時間就是在動畫完成之后。

    有了這一層 scroll 組件的封裝握恳,我們來修改剛剛最復雜的代碼(假設我們已經(jīng)全局注冊了 scroll 組件)瞒窒。

    ? ? ?

      ? ? ?
    • {{item}}
    • ? ?
    ? ?
    ? import BScroll from'better-scroll'exportdefault{

    data() {return{

    data: [],

    pulldown:true}

    },

    created() {this.loadData()

    },

    methods: {

    loadData() {

    requestData().then((res)=>{this.data = res.data.concat(this.data)

    })

    }

    }

    }

    可以很明顯的看到我們的 JS 部分精簡了非常多的代碼,沒有對 better-scroll 再做命令式的操作了乡洼,同時把數(shù)據(jù)請求和 better-scroll 也做了剝離崇裁,父組件只需要把數(shù)據(jù) data 通過 prop 傳給 scroll 組件,就可以保證 scroll 組件的滾動效果就珠。同時寇壳,如果想實現(xiàn)下拉刷新的功能,只需要通過 prop 把 pulldown 設置為 true妻怎,并且監(jiān)聽 pulldown 的事件去做一些數(shù)據(jù)獲取并更新的動作即可壳炎,整個邏輯也是非常清晰的。

    插件 Vue 化引發(fā)的一些思考

    這篇文章我不僅僅是要教會大家封裝一個 scroll 組件逼侦,還想傳遞一些把第三方插件(原生 JS 實現(xiàn))Vue 化的思考過程匿辩。很多學習 Vue.js 的同學可能還停留在 “XX 效果如何用 Vue.js 實現(xiàn)” 的程度,其實把插件 Vue 化有兩點很關鍵榛丢,一個是對插件本身的實現(xiàn)原理很了解铲球,另一個是對 Vue.js 的特性很了解。對插件本身的實現(xiàn)原理了解需要的是一個思考和鉆研的過程晰赞,這個過程可能困難稼病,但是收獲也是巨大的;而對 Vue.js 的特性的了解掖鱼,是需要大家對 Vue.js 多多使用然走,學會從平時的項目中積累和總結(jié),也要善于查閱 Vue.js 的官方文檔戏挡,關注一些 Vue.js 的升級等芍瑞。

    所以,我們拒絕伸手黨褐墅,但也不是鼓勵大家什么時候都要去造輪子拆檬,當我們在使用一些現(xiàn)成插件的同時,也希望大家能多多思考妥凳,去探索一下現(xiàn)象背后的本質(zhì)竟贯,把 “XX 效果如何用 Vue.js 實現(xiàn)” 這句話從問號變成句號。

    以下內(nèi)容是我在作者基礎上添加了一些交互效果逝钥,和作者的放在一起做成一個組件澄耍,可以直接拿去用。為了更容易看懂我的思路,進行了簡要的注釋齐莲。

    {{pulldownTip.text}}
    {{loadingStatus.status}}import BScroll from'better-scroll'exportdefault{

    props: {/**

    * 1 滾動的時候會派發(fā)scroll事件痢站,會截流。

    * 2 滾動的時候?qū)崟r派發(fā)scroll事件选酗,不會截流阵难。

    * 3 除了實時派發(fā)scroll事件,在swipe的情況下仍然能實時派發(fā)scroll事件*/probeType: {

    type: Number,default:1},/**

    * 點擊列表是否派發(fā)click事件*/click: {

    type: Boolean,default:true},/**

    * 是否開啟橫向滾動*/scrollX: {

    type: Boolean,default:false},/**

    * 是否派發(fā)滾動事件*/listenScroll: {

    type: Boolean,default:false},/**

    * 列表的數(shù)據(jù)*/data: {

    type: Array,default:null},/**

    * 是否派發(fā)滾動到底部的事件芒填,用于上拉加載*/pullup: {

    type: Boolean,default:false},/**

    * 是否派發(fā)頂部下拉的事件呜叫,用于下拉刷新*/pulldown: {

    type: Boolean,default:false},/**

    * 是否派發(fā)列表滾動開始的事件*/beforeScroll: {

    type: Boolean,default:false},/**

    * 當數(shù)據(jù)更新后,刷新scroll的延時殿衰。*/refreshDelay: {

    type: Number,default:20},/**

    * 如果啟用loading交互朱庆,傳遞loading的狀態(tài)

    * isShow: false

    * showIcon: false,? ? // 是否顯示loading的icon

    * status: ''? // '正在加載...', '刷新成功', '刷新失敗', ''*/loadingStatus: {

    type: Object,default:function() {return{

    showIcon:false,

    status:''};

    }

    },/**

    * 是否啟用下拉刷新的交互*/pulldownUI: {

    type: Boolean,default:false},/**

    * 是否啟用上拉加載的交互*/pullupUI: {

    type: Boolean,default:false}

    },

    data() {return{

    loadingConnecting:false,

    pulldownTip: {

    text:'下拉刷新',//松開立即刷新rotate:''//icon-rotate},

    };

    },

    mounted() {//保證在DOM渲染完畢后初始化better-scrollsetTimeout(()=>{this._initScroll()

    },20)

    },

    methods: {

    _initScroll() {if(!this.$refs.wrapper) {return;

    }//better-scroll的初始化this.scroll=newBScroll(this.$refs.wrapper, {

    probeType:this.probeType,

    click:this.click,

    scrollX:this.scrollX

    });//是否派發(fā)滾動事件if(this.listenScroll||this.pulldown||this.pullup) {

    let me=this;this.scroll.on('scroll', (pos)=>{if(this.listenScroll) {

    me.$emit('scroll', pos);

    }if(this.pulldown) {//下拉動作if(pos.y>50) {this.pulldownTip={

    text:'松開立即刷新',

    rotate:'icon-rotate'}

    }else{this.pulldownTip={

    text:'下拉刷新',//松開立即刷新rotate:''//icon-rotate}

    }

    }if(this.pullup) {

    }

    })

    }//是否派發(fā)滾動到底部事件,用于上拉加載if(this.pullup) {this.scroll.on('scrollEnd', ()=>{

    console.log('scrollEnd');

    console.log(this.scroll);//滾動到底部if(this.scroll.y<=(this.scroll.maxScrollY+50)) {this.$emit('scrollToEnd');

    }

    });

    }//是否派發(fā)頂部下拉事件闷祥,用于下拉刷新if(this.pulldown) {this.scroll.on('touchend', (pos)=>{//下拉動作if(pos.y>50) {

    setTimeout(()=>{//重置提示信息this.pulldownTip={

    text:'下拉刷新',//松開立即刷新rotate:''//icon-rotate}

    },600);this.$emit('pulldown');

    }

    });

    }//是否派發(fā)列表滾動開始的事件if(this.beforeScroll) {this.scroll.on('beforeScrollStart', ()=>{this.$emit('beforeScroll')

    });

    }

    },

    disable() {//代理better-scroll的disable方法this.scroll&&this.scroll.disable();

    },

    enable() {//代理better-scroll的enable方法this.scroll&&this.scroll.enable();

    },

    refresh() {//代理better-scroll的refresh方法this.scroll&&this.scroll.refresh();

    },

    scrollTo() {//代理better-scroll的scrollTo方法this.scroll&&this.scroll.scrollTo.apply(this.scroll, arguments);

    },

    scrollToElement() {//代理better-scroll的scrollToElement方法this.scroll&&this.scroll.scrollToElement.apply(this.scroll, arguments);

    }

    },

    watch: {//監(jiān)聽數(shù)據(jù)的變化娱颊,延時refreshDelay時間后調(diào)用refresh方法重新計算,保證滾動效果正常data() {

    setTimeout(()=>{this.refresh();

    },this.refreshDelay);

    }

    }

    }$cube-size: 10px; // 項目中用了scss凯砍,沒用的話箱硕,替換掉樣式中的變量即可

    .better-scroll-root{background-color:rgba(7, 17, 27, 0.7);.loading-pos, .pulldown-tip {

    position:absolute;left:0;top:0;width:100%;height:35px;color:#fcfcfc;text-align:center;z-index:2000;}.loading-pos{background-color:rgba(7, 17, 27, 0.7);}.pulldown-tip{top:-50px;height:50px;line-height:50px;z-index:1;}.pull-icon{position:absolute;top:0;left:30%;color:#a5a1a1;font-size:1.5em;transition:all 0.15s ease-in-out;}.pull-icon.icon-rotate{transform:rotate(180deg);}.loading-container{position:absolute;height:$cube-size;width:$cube-size;left:35%;top:50%;transform:translate(-50%, -50%);perspective:40px;}.loading-connecting{line-height:35px;}.cube{height:$cube-size;width:$cube-size;transform-origin:50% 50%;transform-style:preserve-3d;animation:rotate 3s infinite ease-in-out;}.side{position:absolute;height:$cube-size;width:$cube-size;border-radius:50%;}.side1{background:#4bc393;transform:translateZ($cube-size);}.side2{background:#FF884D;transform:rotateY(90deg) translateZ($cube-size);}.side3{background:#32526E;transform:rotateY(180deg) translateZ($cube-size);}.side4{background:#c53fa3;transform:rotateY(-90deg) translateZ($cube-size);}.side5{background:#FFCC5C;transform:rotateX(90deg) translateZ($cube-size);}.side6{background:#FF6B57;transform:rotateX(-90deg) translateZ($cube-size);}@keyframes rotate{0%{

    transform:rotateX(0deg) rotateY(0deg);}50%{transform:rotateX(360deg) rotateY(0deg);}100%{transform:rotateX(360deg) rotateY(360deg);}}

    }

    下拉刷新,上拉加載(暫時未做)悟衩,刷新中等效果如下:

    need-to-insert-img

    need-to-insert-img

    need-to-insert-img

    以上內(nèi)容還不夠精細剧罩,等這段時間忙過去了會繼續(xù)優(yōu)化。如有bug座泳,歡迎各位看官批評指正惠昔。

    ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
    • 序言:七十年代末,一起剝皮案震驚了整個濱河市挑势,隨后出現(xiàn)的幾起案子镇防,更是在濱河造成了極大的恐慌,老刑警劉巖薛耻,帶你破解...
      沈念sama閱讀 206,311評論 6 481
    • 序言:濱河連續(xù)發(fā)生了三起死亡事件营罢,死亡現(xiàn)場離奇詭異赏陵,居然都是意外死亡饼齿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
      沈念sama閱讀 88,339評論 2 382
    • 文/潘曉璐 我一進店門蝙搔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缕溉,“玉大人,你說我怎么就攤上這事吃型≈づ福” “怎么了?”我有些...
      開封第一講書人閱讀 152,671評論 0 342
    • 文/不壞的土叔 我叫張陵,是天一觀的道長枉层。 經(jīng)常有香客問我泉褐,道長,這世上最難降的妖魔是什么鸟蜡? 我笑而不...
      開封第一講書人閱讀 55,252評論 1 279
    • 正文 為了忘掉前任膜赃,我火速辦了婚禮,結(jié)果婚禮上揉忘,老公的妹妹穿的比我還像新娘跳座。我一直安慰自己,他們只是感情好泣矛,可當我...
      茶點故事閱讀 64,253評論 5 371
    • 文/花漫 我一把揭開白布疲眷。 她就那樣靜靜地躺著,像睡著了一般您朽。 火紅的嫁衣襯著肌膚如雪狂丝。 梳的紋絲不亂的頭發(fā)上,一...
      開封第一講書人閱讀 49,031評論 1 285
    • 那天虚倒,我揣著相機與錄音美侦,去河邊找鬼。 笑死魂奥,一個胖子當著我的面吹牛菠剩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耻煤,決...
      沈念sama閱讀 38,340評論 3 399
    • 文/蒼蘭香墨 我猛地睜開眼具壮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哈蝇?” 一聲冷哼從身側(cè)響起棺妓,我...
      開封第一講書人閱讀 36,973評論 0 259
    • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炮赦,沒想到半個月后怜跑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
      沈念sama閱讀 43,466評論 1 300
    • 正文 獨居荒郊野嶺守林人離奇死亡吠勘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
      茶點故事閱讀 35,937評論 2 323
    • 正文 我和宋清朗相戀三年性芬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剧防。...
      茶點故事閱讀 38,039評論 1 333
    • 序言:一個原本活蹦亂跳的男人離奇死亡植锉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出峭拘,到底是詐尸還是另有隱情俊庇,我是刑警寧澤狮暑,帶...
      沈念sama閱讀 33,701評論 4 323
    • 正文 年R本政府宣布,位于F島的核電站辉饱,受9級特大地震影響搬男,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜彭沼,卻給世界環(huán)境...
      茶點故事閱讀 39,254評論 3 307
    • 文/蒙蒙 一止后、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧溜腐,春花似錦译株、人聲如沸。這莊子的主人今日做“春日...
      開封第一講書人閱讀 30,259評論 0 19
    • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至望众,卻和暖如春匪补,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背烂翰。 一陣腳步聲響...
      開封第一講書人閱讀 31,485評論 1 262
    • 我被黑心中介騙來泰國打工夯缺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甘耿。 一個月前我還...
      沈念sama閱讀 45,497評論 2 354
    • 正文 我出身青樓踊兜,卻偏偏與公主長得像蛹屿,于是被迫代替她去往敵國和親颅眶。 傳聞我的和親對象是個殘疾皇子勒叠,可洞房花燭夜當晚...
      茶點故事閱讀 42,786評論 2 345

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