2020-03 技術(shù)匯總

2020/03/30 周一

#JSON數(shù)據(jù)轉(zhuǎn)Blob后勺远,怎么還原

在axios請(qǐng)求下載文件接口時(shí)翘地,一般設(shè)置responseType: 'blob'馏予,文件返回正常就沒問題吃谣,但后臺(tái)如果處理文件或鑒權(quán)有問題酪碘,接口返回了包含錯(cuò)誤信息的json格式數(shù)據(jù),那樣json數(shù)據(jù)也會(huì)轉(zhuǎn)為Blob對(duì)象吉嫩,而前端有必要將錯(cuò)誤信息展示的其掂,那怎么將Blob數(shù)據(jù)轉(zhuǎn)JSON呢?下面來看看

let fileType = res.headers['content-type']
if (fileType.startsWith('application/json')) {
  let reader = new FileReader();
  reader.addEventListener("loadend", function() {
    let data = JSON.parse(reader.result)
    console.log(data);
  });
  reader.readAsText(res.data, "UTF-8") // 加UTF-8防止中文亂碼
  return
}

#2020/03/28 周六

#網(wǎng)頁dark mode(深色模式)適配

微信最近推出了深色模式吴菠,我試了下者填,手機(jī)切換時(shí)頁面效果樣式是實(shí)時(shí)刷新的。于是就想著web怎么能夠監(jiān)聽深色模式做葵,并設(shè)置樣式占哟。查了資料后,在Stack Overflow上找到了答案

通過css里的媒體查詢就能適配深色模式,先來看看怎么用js獲取當(dāng)前是否是深色模式

// 獲取當(dāng)前是否是深色模式
// window.matchMedia('(prefers-color-scheme: dark)').matches
window.matchMedia && console.log('Is dark mode: ', window.matchMedia('(prefers-color-scheme: dark)').matches)

// 用js監(jiān)聽深色模式的切換事件
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
  console.log('dark mode change榨乎,已' + (event.matches ? '進(jìn)入': '退出') + 'dark mode')
})

window.matchMedia到底是用來做什么的怎燥?我查了下mdn,發(fā)現(xiàn)了這樣一個(gè)示例

let mql = window.matchMedia('(max-width: 600px)');

document.querySelector(".mq-value").innerText = mql.matches;

從這個(gè)例子看蜜暑,大概就知道怎么用css來支持dark模式了吧铐姚,就是加一個(gè)類似小屏適配的一個(gè)媒體查詢樣式,來看個(gè)例子

/* dark mode support */
@media (prefers-color-scheme: dark) {
  body {
    background-color: black;
    color: #aaa;
  }

  body .content article, header, aside > div, footer  {
    border-color: #333;
    color: #aaa;
    background-color: black;
    box-shadow: 0 0 10px #333;
  }
}

深色模式下肛捍,一般將背景調(diào)暗隐绵,字體設(shè)置為偏白色即可。zuo11.com 已用上面的方法適配了深色模式拙毫,可以體驗(yàn)下依许。網(wǎng)站是開源的,zuo11.com深色模式支持代碼 - github(opens new window)

參考:

#2020/03/27 周五

#canvas繪制模糊的問題

今天發(fā)現(xiàn)同樣的代碼在兩臺(tái)電腦上繪制的一個(gè)清晰缀蹄,一個(gè)模糊峭跳,后來查資料發(fā)現(xiàn)確實(shí)有這個(gè)問題

因?yàn)閏anvas不是矢量圖,高dpi屏幕每平方英寸有更多的像素缺前,也就是兩倍屏蛀醉,瀏覽器會(huì)以兩個(gè)像素點(diǎn)的寬度來渲染一個(gè)像素,所以在Retina屏上會(huì)導(dǎo)致圖片衅码、文字都會(huì)模糊拯刁,怎么解決呢?

獲取設(shè)備像素比:window.devicePixelRatio || 1

如果繪制的實(shí)際區(qū)域大小為 750 * 40肆良,假設(shè)設(shè)備像素比為2筛璧,那么,canvas的width惹恃、height需要設(shè)置為 1500 * 80夭谤,然后用內(nèi)聯(lián)樣式設(shè)置width為750,height為40巫糙,相當(dāng)于canvas繪制2倍的大小朗儒,然后再縮放,這樣就清晰了参淹。

綜上醉锄,在canvas繪制時(shí),各種長度一定要考慮乘以devicePixelRatio浙值,不然可能顯示的不清晰

參考:解決 canvas 在高清屏中繪制模糊的問題(opens new window)

#2020/03/26 周四

#canvas不支持文本換行怎么處理

今天在stackoveflow里面搜索ctx.fill的問題時(shí)恳不,查到了很多關(guān)于canvas ctx.fillText()繪制文本時(shí)不支持換行的問題,找到了一個(gè)比較好的答案

I'm afraid it is a limitation of Canvas' fillText. There is no multi-line support. Whats worse, there's no built-in way to measure line height, only width, making doing it yourself even harder!

一般解決思路是开呐,根據(jù) ctx.measureText('Hello').width 來看需要顯示的文字是否需要換行烟勋,寫一個(gè)for循環(huán)來處理

參考:

#canvas繪制不規(guī)則形狀填充漸變色

在JS高程3中规求,有一章專門將使用canvas繪圖,今天終于用上了卵惦,效果還不錯(cuò)阻肿,來看效果,原生js沮尿,70行不到

cavas_unnormal_shape.png
<canvas id="drawing1" width="720" height="45" >A draw of something.</canvas>
<script>
  drawStatus('drawing1', 2)
  function drawStatus(domId, position) {
    let str = ['① 狀態(tài)一', '② 狀態(tài)二', '③ 狀態(tài)三', '④ 狀態(tài)四', '⑤ 狀態(tài)五', '⑥ 狀態(tài)六']
    let config = {
      width: 100,
      height: 40,
      extendLength: 20,
      radius: 4
    }
    let config2 = { ...config, width: 110 }
    let cur = str.length - position

    str.reverse().forEach((item, index) => {
      let pos = str.length - index - 1
      let x = 0 + (str.length - 1) * config.radius
      if (pos !== 0) {
        x = (pos * 100) + (pos -1) * 10 + (str.length - 1 - pos) * config.radius
      }
      console.log(pos,x)
      let curConfig = pos === 0 ? config : config2 
      if (pos < (str.length - cur)) {
        curConfig.isFocus = true
      }
      drawUnnormalShape(domId, x , 0, str[index], curConfig)
    })
  }

  function drawUnnormalShape(domId, x, y, text, config) {
    let drawing = document.getElementById(domId);
    let ctx = drawing.getContext('2d');
    let { width, height, extendLength, radius, isFocus } = config 
    ctx.beginPath(); // 如果都需要重新beginPath 不然丛塌,后面的fill會(huì)覆蓋前面的fill

    // 不規(guī)則矩形
    ctx.moveTo(x + radius, y) // 從左上角 (x + radius, y) 位置開始
    ctx.arcTo(x, y, x, y + radius, radius) // 左上圓角
    ctx.lineTo(x, y + height - 2 * radius) // 畫左邊
    ctx.arcTo(x, y + height, x + radius, y + height, radius) // 左下圓角
    ctx.lineTo(x + width - radius, y + height) // 下邊
    // ctx.arcTo(x + width - radius, y + height, x + width - radius, y + height - 1, 1) // 圓角

    let extendEndX = x + width + extendLength
    let middleHeight = y + height / 2
    ctx.arcTo(extendEndX, middleHeight, extendEndX - radius, middleHeight - radius, radius) // 線 + 圓角
    ctx.lineTo(x + width - radius, y)
    ctx.lineTo(x + radius, y)

    var gradient = ctx.createLinearGradient(x, y + height / 2, x + width + extendLength, y + height / 2); // 從(130,130)到(160,160)漸變
    gradient.addColorStop(0, isFocus ? '#62ccff' : '#fff'); // 漸變的起點(diǎn)色
    gradient.addColorStop(1, isFocus ? '#0486fe' : '#fff'); // 漸變的結(jié)束色

    ctx.shadowOffsetX = 6;
    ctx.shadowOffsetY = 2;
    ctx.shadowBlur = 16; // 模糊像素
    ctx.shadowColor = "rgba(58, 86, 111, 0.15)";

    ctx.fillStyle = gradient
    ctx.fill() // ctx.stroke()

    let textArr = text.split(' ')
    ctx.font = "15px arial"
    ctx.fillStyle = isFocus ? '#fff' : '#ccc'
    ctx.fillText(textArr[0], x + width / 2 - 20, y + height / 2 + 5)
    ctx.font = "11px arial"
    ctx.fillText(textArr[1], x + width / 2, y + height / 2 + 4)
  }
</script>

參考之前的筆記:使用canvas繪圖 - JS高程3筆記(opens new window)

完整demo: canvas畫不規(guī)則形狀填充漸變背景 - github(opens new window)

#canvas 多次fill會(huì)覆蓋前面的fill

在使用canvas進(jìn)行繪圖時(shí),封裝了一個(gè)繪制函數(shù)畜疾,每次都會(huì)填充顏色 ctx.fill()赴邻,如果多次執(zhí)行,只會(huì)在最后一次時(shí)啡捶,整體fill一次乍楚?

剛開始以為是后面的fill覆蓋了前面的fill,后來網(wǎng)上查了下届慈,第一次fill后,再次fill需要再次調(diào)用ctx.beginPath()忿偷,不然只會(huì)在最后一次fill金顿。

參考: HTML5的canvas標(biāo)簽為什么會(huì)覆蓋之前畫的東西的顏色 (opens new window)

#2020/03/25 周三

#根據(jù)文件名后綴判斷文件類型不準(zhǔn)確

比如我有個(gè)1.png文件,我修改下后綴名 1.txt鲤桥,那前端如果僅憑文件名的后綴來顯然是不行的揍拆,我們需要根據(jù)文件類型的二進(jìn)制數(shù)據(jù)標(biāo)記來判斷對(duì)應(yīng)的文件類型,這樣才會(huì)更加準(zhǔn)確茶凳,安全性更高

判斷文件類型.png

#怎么判斷兩個(gè)文件一模一樣

一般文件的md5可能會(huì)有重復(fù)的嫂拴,怎么減少這種概率呢?校驗(yàn)分三個(gè)部分

  1. 比較整個(gè)文件的md5
  2. 選擇文件固定位置的幾個(gè)片段分別計(jì)算md5進(jìn)行比對(duì)
  3. 比較文件名是否一樣

#md5加密是可逆的嗎贮喧?

理論上md5加密后筒狠,在不知道原始消息的前提下,是無法憑借16個(gè)字節(jié)的消息摘要(Message Digest)箱沦,還原出原始的消息的.

但為什么有些網(wǎng)站可以破解md5加密后的密碼呢辩恼?主要是使用的碰撞檢測。它會(huì)提前算出一些常用弱密碼的md5值谓形,一個(gè)個(gè)比較灶伊。才會(huì)讓人產(chǎn)生md5可逆的錯(cuò)覺。一般除了md5加密外寒跳,我們可以再多進(jìn)行一些處理(加鹽)聘萨,來進(jìn)行干擾,提高破解難度

參考:為什么說 MD5 是不可逆的童太?(opens new window)

#兩個(gè)不同文件md5可能一樣嗎米辐?

什么是md5胸完?md5 是 messge digest [da??d?est] 5 的縮寫,意思是信息摘要算法

linux下儡循,在terminal中執(zhí)行man md5舶吗,可以查看對(duì)應(yīng)的文檔

md5 -- calculate a message-digest fingerprint (checksum) for a file

md5 -- 為一個(gè)文件計(jì)算信息摘要指紋('校驗(yàn)和'或'校驗(yàn)碼')

md5 -s '123456'
# MD5 ("123456") = e10adc3949ba59abbe56e057f20f883e

md5 1.txt
# MD5 (1.txt) = 6f74626e0749e5353cc7e11767418d43

從上面的例子中我們可以看到,將文件或字符串進(jìn)行 md5校驗(yàn) 會(huì)生成一個(gè) 32位 的校驗(yàn)碼择膝。問題來了誓琼,網(wǎng)上看到 md5加密后一般是128位,而這里只有32位為什么呢肴捉?我們要分清16進(jìn)制與2進(jìn)制腹侣,標(biāo)準(zhǔn)說法是,md5加密后的字符為 128bit(16字節(jié))齿穗,而一個(gè)我們看到的32位是16進(jìn)制傲隶,每一位都可以轉(zhuǎn)為4bit,也就是4個(gè)二進(jìn)制位窃页。1 - f 分別對(duì)應(yīng) 0000 - 1111跺株,所以128bit

一個(gè)二進(jìn)制位(bit)只能表示0或1兩種情況,128bit可以表示 Math.pow(2, 128) 2的128次方種情況脖卖,定死了乒省,最多只能表示這么多種情況,不同內(nèi)容的文件實(shí)在是太多了畦木,理論上絕對(duì)是會(huì)超過2的128次方的袖扛。

綜上:兩個(gè)不同文件md5是有可能相同的,因?yàn)閙d5最多只能表示2的128次方種情況十籍,而不同的文件絕對(duì)大于這個(gè)數(shù)

雖然兩個(gè)文件的md5可能一致蛆封,但給定一個(gè)文件的md5值,想偽造另一個(gè)文件的md5值與該值一樣勾栗,相對(duì)還是比較困難的惨篱,因此可用于判斷文件完整性

參考: 有沒有兩個(gè)完全不一樣的文件,但是他們的md5值是一樣的械姻?(opens new window)

#2020/03/22 周日

#koa-multer與@koa/multer邏輯差異

之前有了解過以@開頭的作用域包妒蛇,這次在使用koa-multer這個(gè)模塊時(shí),發(fā)現(xiàn)@koa/multer與koa-multer的邏輯居然不一樣楷拳。源碼有些差異绣夺,下面來具體看看

// 在使用 koa-multer 時(shí)
const multer = require('koa-multer')
router.post('/test', multer().none(), ctx => { 
  let isFormData = ctx.headers['content-type'].startsWith('multipart/form-data')
  // ctx.req node的request對(duì)象, ctx.request koa的request對(duì)象
  ctx.body = isFormData ? ctx.req.body : ctx.request.body
})

koa-multer這個(gè)包是從express的multer包上面加了一層封裝,而koa-multer并沒有把fileds字段掛載到ctx.request.body上欢揖,只維持原來express那樣掛載到node的request對(duì)象上陶耍,也就是ctx.req.body,來看看koa-multer的源碼部分

// https://github.com/koa-modules/multer/blob/master/index.js
multer[name] = function () {
    const middleware = fn.apply(this, arguments)

    return (ctx, next) => {
      return new Promise((resolve, reject) => {
        middleware(ctx.req, ctx.res, (err) => {
          err ? reject(err) : resolve(ctx)
        })
      }).then(next)
    }
  }

而@koa/multer則做了處理她混,可以與上面的例子對(duì)比下

// https://github.com/koajs/multer/blob/master/index.js
multer[name] = function() {
    const middleware = Reflect.apply(fn, this, arguments);

    return (ctx, next) => {
      return new Promise((resolve, reject) => {
        middleware(ctx.req, ctx.res, err => {
          if (err) return reject(err);
          if ('request' in ctx) {
            if (ctx.req.body) {
              ctx.request.body = ctx.req.body;
              delete ctx.req.body;
            }

            if (ctx.req.file) {
              ctx.request.file = ctx.req.file;
              ctx.file = ctx.req.file;
              delete ctx.req.file;
            }

            if (ctx.req.files) {
              ctx.request.files = ctx.req.files;
              ctx.files = ctx.req.files;
              delete ctx.req.files;
            }
          }

          resolve(ctx);
        });
      }).then(next);
    };
  };

我們?cè)賮砜纯词褂聾koa/multer的情況烈钞,就比較方便了泊碑,和其他數(shù)據(jù)一樣掛載到 ctx.request.body

const multer = require('@koa/multer')
router.post('/test', multer().none(), ctx => { 
  ctx.body = ctx.request.body
}) 

綜上,如果某個(gè)模塊有兩種包名毯欣,建議先考慮@開頭的作用域包馒过,通常這種功能會(huì)新點(diǎn)。后面迭代維護(hù)應(yīng)該都是以這個(gè)為準(zhǔn)

#2020/03/20 周五

#npm包前面加@是什么意思(vue-cli與@vue/cli)

Vue CLI 的包名稱由 vue-cli 改成了 @vue/cli酗钞。 如果你已經(jīng)全局安裝了舊版本的 vue-cli (1.x 或 2.x)腹忽,你需要先通過 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸載它。

今天看vue-cli文檔砚作,發(fā)現(xiàn)上面的這段話 vue-cli 改為了 @vue/cli窘奏,這兩個(gè)npm有什么區(qū)別呢?npm包前面加@是什么意思葫录,查了下官網(wǎng)

npm包前面加@着裹,代表scopes相關(guān)的包,可以理解為作用域(范圍)包米同,作用域使我們可以創(chuàng)建與其他用戶或組織創(chuàng)建的包同名骇扇,而不會(huì)發(fā)生沖突。

A scope allows you to create a package with the same name as a package created by another user or Org without conflict.

作用域名稱是介于@和斜線之間的所有內(nèi)容:

The scope name is everything between the @ and the slash:

// “npm” scope:
@npm/package-name
// “npmcorp” scope:
@npmcorp/package-name

npm包一個(gè)詬病就是包名很容易被占用的問題面粮,占用后用其他人就不能用了匠题。而作用域包類似于創(chuàng)建了一個(gè)命名空間,不同的命名空間但金,可以使用相同的包名

作用域的命名不是誰便就能用的,只有兩種可以使用:自己的用戶名郁季、自己創(chuàng)建的組織名

注意:必須先注冊(cè)一個(gè)npm用戶帳戶冷溃,然后才能發(fā)布用戶作用域的npm軟件包。此外梦裂,要發(fā)布組織作用域的軟件包似枕,您必須創(chuàng)建一個(gè)npm用戶帳戶,然后創(chuàng)建一個(gè)npm Org(組織)年柠。

在 vue-cli 中可以用@vue/cli說明使用了vue這個(gè)npm賬號(hào)或者組織發(fā)布了該包凿歼。

參考:

#2020/03/18 周三

#md怎么加引用注釋答憔,腳注

這里有一個(gè)注腳[^1],這段話的還有其他意思[^2]在里面

[^1]:這里是注腳內(nèi)容
[^2]:這里是其他意思的注腳

注腳放到中間也可以

這里有一個(gè)注腳^1掀抹,這段話的還有其他意思^2在里面

注腳放到中間也可以

#md中鏈接的另一種寫法

我是一段文字虐拓,[baidu][1]、[qq][2]里面有鏈接

[1]: http://baidu.com "baidu"
[2]: http://qq.com "qq"

我是一段文字傲武,baidu (opens new window)蓉驹、qq (opens new window)里面有鏈接

#2020/03/17 周二

#Node.js的核心用處及應(yīng)用場景

  1. 打包構(gòu)建城榛、工程化,主要依賴基礎(chǔ)的fs模塊态兴,文件讀寫狠持,如xxx-cli(腳手架)、webpack瞻润、parcel喘垂、hexo,node在打包構(gòu)建敢订、前端工程化這塊基本影響了整個(gè)前端的開發(fā)過程王污,各框架基本都有基于node的cli,快速生成腳手架楚午,使開發(fā)更加高效昭齐、規(guī)范。

  2. 寫后臺(tái)接口矾柜,主要依賴基礎(chǔ)的http模塊阱驾,處理請(qǐng)求和響應(yīng)箫老,如 express.js疯淫、koa.js,一般主要用于模擬假數(shù)據(jù)接口, 調(diào)UI烹骨、交互效果以及做一些請(qǐng)求響應(yīng)方面的自測

  3. 綜合應(yīng)用:獲取數(shù)據(jù)+渲染頁面(高并發(fā)缆瓣、高性能)喧枷,koa.js對(duì)于開發(fā)商業(yè)化應(yīng)用來說還是比較單薄,egg.js基于koa做了一些增強(qiáng)弓坞,讓node也可以做企業(yè)級(jí)應(yīng)用隧甚。阿里的使用場景就是一個(gè)很好的例子,基礎(chǔ)設(shè)施大部分采用 Java 實(shí)現(xiàn)渡冻,變化較少戚扳,有事務(wù)要求的 Business Services 通常使用 Java。而Node主要用于替代過去php族吻、jsp使用場景, 用在需要快速迭代帽借,需求變化非常快的用戶側(cè)超歌。node已經(jīng)經(jīng)受了阿里雙11的考驗(yàn)砍艾,技術(shù)上是可行的。

題外話:個(gè)人認(rèn)為綜合應(yīng)用這塊巍举,自己玩玩還可以辐董,小團(tuán)隊(duì)或node不是非常強(qiáng)的技術(shù)團(tuán)隊(duì)盡量不要嘗試,阿里能做好這塊是因?yàn)閲鴥?nèi)頂尖的node方面人才基本都在阿里禀综,經(jīng)過多年實(shí)踐踩坑简烘,擁有相對(duì)完善的node基建和生態(tài)苔严。目前市面上前端里node強(qiáng)的比較少,餓了么為了招node服務(wù)端開發(fā)孤澎,還專門寫了個(gè)node相關(guān)的面試教程届氢。可想而知這方面人才有多少覆旭。

node支持高并發(fā)的原因:

  • node.js基于異步I/O退子,接收到請(qǐng)求后,直接開一個(gè)I/O線程去執(zhí)行型将,然后就不管了寂祥,立即繼續(xù)執(zhí)行主線程。等I/O線程執(zhí)行完成后七兜,直接執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)即可丸凭。省去了許多等待請(qǐng)求的時(shí)間
  • 事務(wù)驅(qū)動(dòng),主線程通過event loop事件循環(huán)觸發(fā)的方式來運(yùn)行程序腕铸,這一條暫時(shí)還不是很理解惜犀,先寫上~

參考:

#webpack與parcel區(qū)別

webpack與parcel都是打包工具狠裹,webpack功能強(qiáng)大虽界,但比較重,配置項(xiàng)比較多涛菠,有點(diǎn)繁瑣莉御。而parcel就是為了解決配置項(xiàng)太多這個(gè)問題的,它默認(rèn)集成了通用的常規(guī)功能俗冻,零配置颈将,如果自定義較多,還是推薦webpack

If you don't want to worry about configuring everything and your needs are common needs, you should go directly with parcel. Parcel provides defaults (for babel-preset-env, post-css, html, etc) that fits most scenarios and works for everybody. You don't have to worry about configuring anything.

From the other hand, if you need a more customization, you should go with webpack. Keep in mind that you will have to setup everything that you need, explicitly set those things.

參考:Webpack vs Parcel - Stack Overflow(opens new window)

#mac使用觸控板拖動(dòng)復(fù)制言疗、移動(dòng)窗口

今天才意識(shí)到,每次要復(fù)制一段文字或移動(dòng)某個(gè)應(yīng)用窗口颂砸,我都是點(diǎn)擊觸控板再拖動(dòng)噪奄。而且Mac Air的觸控板按的聲音比較響,于是找了下是否有手勢可以支持人乓。

發(fā)現(xiàn)可以設(shè)置使用 三指拖移 復(fù)制文字和拖動(dòng)窗口勤篮,三個(gè)手指放上去拖動(dòng)就可以了。

設(shè)置方法:打開系統(tǒng)統(tǒng)偏好設(shè)置 => 點(diǎn) “輔助功能” => 點(diǎn) “鼠標(biāo)與觸控板” => 點(diǎn) “觸控板選項(xiàng)” => 先勾上啟用拖移色罚,然后選擇“三指拖移”碰缔,點(diǎn)擊 “好”

圖文詳情參考: MacBook觸控板選中/復(fù)制(opens new window)

#2020/03/12 周四

#關(guān)于vue和react思考

我個(gè)人理解 vue組件設(shè)計(jì)的對(duì)新手超級(jí)友好,使用門檻很低戳护。雖然我沒用過react金抡,但我可以猜到React應(yīng)該也是犧牲了一定的用戶使用門檻瀑焦,來實(shí)現(xiàn)更加靈活的js控制。而vue犧牲了用js控制的靈活度來降低了用戶使用門檻梗肝。側(cè)重點(diǎn)不一樣榛瓮,但底層實(shí)現(xiàn)基本都差不多,比如虛擬dom巫击、hooks禀晓,只是開放給用戶的調(diào)用方式不一樣。

前端框架再怎么變動(dòng)坝锰,就算弄出一朵花來粹懒,也只是對(duì)dom的修改,最終還是會(huì)回歸到 js高程3里面講到的dom章節(jié)部分內(nèi)容顷级。

#git commit 提交信息有誤怎么修改

如果不小心提交了凫乖,但沒有push,可以使用下面的命令來修改上一次的commit信息

git commit --amend -m 'xxx'

#他人提交了package-lock.json的更新導(dǎo)致拉取時(shí)和本地沖突

一般在npm install 時(shí)會(huì)修改package-lock.json文件愕把,我一般不會(huì)提交這個(gè)更新拣凹,但今天發(fā)現(xiàn)有人提交。我拉取時(shí)恨豁,提示這個(gè)文件沖突嚣镜,導(dǎo)致拉取不下來,我又不想提交更新橘蜜,所以嘗試用下面的命令菊匿,將工作區(qū)該文件的修改丟棄,再拉取

git checkout -- package-lock.json

拉取成功后计福,npm run serve 基本沒什么影響

#2020/03/11 周三

#vue封裝組件方式的思考

在封裝組件時(shí)跌捆,一般我們使用的方法是

把組件單獨(dú)放到一個(gè)xx.vue,然后需要引入時(shí)在components使用懶加載引入再使用

我就在想象颖,每次引入組件都需要三步

  1. 把組件通過 components 引入
  2. 在template中寫對(duì)應(yīng)的代碼
  3. 在data中寫對(duì)應(yīng)的數(shù)據(jù)佩厚,methods里寫綁定的事件

會(huì)不會(huì)太麻煩了,我希望像element的組件那樣说订,通過 this.$message.error(e.message) 這樣直接調(diào)用一個(gè)組件

于是我嘗試使用js的方式來調(diào)用單文件組件(.vue)抄瓦,在之前02/20號(hào)寫過方法,除了直接掛載到body外陶冷,也可以掛載到任何地方钙姊,只要你能拿到對(duì)應(yīng)的dom,可以使用ref屬性埂伦,再通過this.$refs['xx']來獲取其DOM 元素和組件實(shí)例煞额。

// 引入該組件
import ShowInfo from 'showInfo.vue'

// 通過js調(diào)用
clickShow() {
  // 創(chuàng)建一個(gè)vue組件
  const Component = Vue.extend(ShowInfo)

  // 在文檔之外渲染并且隨后掛載,返回對(duì)應(yīng)的Vue實(shí)例(vm)
  let showInfoVue = new Component().$mount() 

  // 將組件實(shí)例的dom,append到當(dāng)前頁面body下
  this.$el.appendChild(showInfoVue.$el) 
}

其實(shí)你發(fā)現(xiàn)沒膊毁,用js直接調(diào)用vue組件可以是可以胀莹,但也要比正常情況下寫更多代碼,比如

  1. js調(diào)用vue的方法需要封裝為一個(gè)class
  2. 以上面的示例為例子媚媒,通過js調(diào)用組件嗜逻,我們需要一個(gè)成功的回調(diào),以及傳參到組件缭召,在獲取到ShowInfo時(shí)栈顷,我們需要知道我們引入的只是一個(gè)'js對(duì)象'。我們可以在對(duì)象的methods里面注入方法嵌巷,用來獲取傳入的值萄凤,或掛載成功后的回調(diào)。這樣相當(dāng)于mixin搪哪,但.vue組件實(shí)現(xiàn)里使用這些注入的事件時(shí)會(huì)不好理解靡努,有種默認(rèn)其妙多出來全局函數(shù)的疑惑
  3. 以js方法寫的組件,不能兼容默認(rèn)的引用方法晓折,如果要支持那就要寫一些額外的代碼
  4. 你會(huì)發(fā)現(xiàn)邏輯會(huì)變的不好理解惑朦,不夠簡單,對(duì)新手不友好漓概,如果需要其他人維護(hù)時(shí)漾月,可能不好理解為什么這么做

綜上所述:默認(rèn)的封裝調(diào)用組件的方式就很好,簡單胃珍、明了梁肿,你想在調(diào)用的時(shí)候輕松,那么在封裝組件時(shí)觅彰,就會(huì)增加對(duì)應(yīng)的工作量吩蔑,整體工作量差不多。

我們?cè)賮砜磂lement組件填抬,對(duì)于內(nèi)容比較少的烛芬,比如通知類,element都提供的是js調(diào)用方法飒责,而沒有普通的組件調(diào)用方法赘娄。且一般掛載到body上。為什么dialog組件沒有封裝成js呢读拆?我的理解是dialog里面的內(nèi)容可擴(kuò)展性很強(qiáng),如果改為js調(diào)用鸵闪,可能會(huì)出現(xiàn)把大量代碼寫在js的情況檐晕,或者需要寫VNode的render方法。就顯得不夠優(yōu)雅了。

總結(jié):在封裝組件時(shí)辟灰,什么時(shí)候用封裝為js調(diào)用方式个榕、什么時(shí)候采用普通的封裝呢?我的理解是可以通過下面幾個(gè)方面來進(jìn)行評(píng)估

  1. 被封裝的組件需求是否穩(wěn)定芥喇,有沒有可能會(huì)在后面經(jīng)常變更或者進(jìn)行漸進(jìn)式增強(qiáng)西采,如果不穩(wěn)定,不建議封裝為js調(diào)用方式继控,對(duì)于可擴(kuò)展性強(qiáng)的械馆,還是建議使用普通組件封裝方式,更利于維護(hù)
  2. 是否是掛載到body下武通,還是需要放到任意的div內(nèi)? 一般普通組件更好放置霹崎。如果掛載到body下,可以考慮封裝為js調(diào)用方式
  3. 是否功能相對(duì)單一簡單冶忱,如果組件功能單一簡單建議封裝為js調(diào)用方式
  4. 該組件是否在頁面里大量被調(diào)用 大量的被調(diào)用尾菇,意味著大量重復(fù)的代碼,可以考慮封裝為js調(diào)用方式囚枪,增加組件實(shí)現(xiàn)時(shí)的復(fù)雜度派诬,來降低調(diào)用時(shí)的復(fù)雜度

總之,不管怎么樣封裝链沼,當(dāng)有人問你為什么這么封裝時(shí)默赂,你要能夠說出你自己的理由。

#2020/03/10 周二

#vue自定義組件v-model屬性實(shí)現(xiàn)dialog組件的二次封裝

當(dāng)某個(gè)組件是element的dialog組件時(shí)忆植,我們需要對(duì)dialog進(jìn)行隱藏顯示放可,當(dāng)子組件里的dialog關(guān)閉時(shí),需要修改父組件傳入的值朝刊,盡管不是表單組件也可以使用v-model來解決耀里,先來看看怎么調(diào)用

<template>
  <div>
    <user-selection v-model="showUserSelection" @confirm="confirm"/>
    <el-button type="primary" @click="showUserSelection = true">打開彈窗</el-button>
  <div>
<template>
<script>
export default {
  components: {
    UserSelection: () => import("../src/components/user-selection/src/main")
  },
  data() {
    return {
      showUserSelection: false
    }
  },
  methods: {
    confirm(value) {
      console.log(value)
    }
  }
}
</script>

再來看組件實(shí)現(xiàn)

<template>
  <div>
    <el-dialog title="提示" :visible.sync="dialogVisible">
      內(nèi)容
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">確 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
export default {
  model: {
    prop: 'show', // 設(shè)置對(duì)應(yīng)v-model的屬性字段
    event: 'close' // 如果不指定默認(rèn)為input,當(dāng)$emit該事件拾氓,可以自動(dòng)執(zhí)行 修改父組件v-model參數(shù)的值
  },
  props: ['show'], // 接收v-model的傳值
  computed: {
    dialogVisible: {
      get() {
        return this.show
      },
      set(newVal) {
        console.log(newVal)
        this.$emit('close', newVal)
      }
    }
  },
  data() {
    return {}
  }
}
</script>

#封裝組件時(shí)預(yù)留vue插件入口便于全局引入

在element組件中冯挎,我們使用el-input等element元素時(shí),不需要在components里引入咙鞍。為什么呢房官?在引入element時(shí),我們有在mian.js里我們使用了Vue.use(elemnt組件)续滋,這樣進(jìn)行了全局注入組件翰守,相當(dāng)于組件做成了一個(gè)vue插件,如果我們自己封裝組件如何能夠在Vue.use后直接可以全局調(diào)用呢疲酌?

于是我特意去看了下element組件源碼蜡峰,這里我們暫時(shí)不要求封裝為npm包了袁,只需要在平常自定義組件的基礎(chǔ)上做一個(gè)增強(qiáng),可以使用Vue.use全局引入湿颅。

element-ui源碼中载绿,以alert組件為例,來看目錄結(jié)構(gòu)

alert
├── src
│   └── main.vue  # 組件實(shí)現(xiàn)
└── index.js # install方法油航,供全局引入

import Alert from './src/main';

/* istanbul ignore next */
Alert.install = function(Vue) {
  Vue.component(Alert.name, Alert);
};

export default Alert;

綜上:我們?cè)陂_發(fā)組件時(shí)崭庸,可以增加全局引入的接口,層級(jí)也可以仿照element的來谊囚,多研究源碼這樣代碼才會(huì)寫的更健壯怕享。

#css hover后改變其他元素樣式

css中某個(gè)元素hover后,可以對(duì)其他元素設(shè)置樣式秒啦,但注意:只限定于改變他的子元素, 以及其后面的元素

<style>
  /* hover后單獨(dú)改變某一個(gè)子元素的樣式 */
  .cur-element:hover .child-1 {
    color: red;
  }
  /* 設(shè)置相鄰的后一個(gè)兄弟節(jié)點(diǎn)樣式 */
  .cur-element:hover + div {
    background: blue;
  }
  /* 設(shè)置后面的所有對(duì)應(yīng)的兄弟節(jié)點(diǎn)樣式熬粗,不必相鄰,但需要再其后面 */
  .cur-element:hover ~ div {
    background: red;
  }
</style>
<div class="parent">
  <div>再前一個(gè)兄弟元素</div>
  <div>前一個(gè)兄弟元素</div>
  <div class="cur-element">
    測試hover
    <span class="child-1">child-1</span>
    <span class="child-2">child-2</span>
  </div>
  <div>后一個(gè)兄弟元素</div>
  <div>再后一個(gè)兄弟元素</div>
  <div>再再后一個(gè)兄弟元素</div>
</div>

參考:

#css vw的使用場景

在輪播圖純css的解決方案中:

  • 將圖片區(qū)域?qū)挾仍O(shè)置為 圖片張數(shù) * 100%
  • hover切換按鈕時(shí)余境,將圖片區(qū)域向左移動(dòng)一個(gè)100%:transform: translateX(100%)

這里就會(huì)有問題驻呐,向左移動(dòng)100%,寬度是圖片張數(shù)*100%芳来,而不是視窗寬度含末,用 100vw就可以很好的解決了。

參考之前的css筆記:css長度單位 相對(duì)長度 - HTML權(quán)威指南CSS部分(opens new window)

#2020/03/08 周日

#widnows nginx部署https服務(wù)

今天打算用使用 zuo11.com的 二級(jí)域名 api 來寫接口玩玩即舌,打算使用https佣盒。

  1. 在阿里云將域名免費(fèi)的ssl證書分配給api.zuo11.com
  2. 在域名解析里,增加 api.zuo11.com 的解析顽聂,解析到服務(wù)器
  3. 初始化一個(gè)koa項(xiàng)目肥惭,監(jiān)聽某個(gè)端口,比如 9000端口紊搪,寫一些測試的接口
  4. 部署到服務(wù)器
  5. nginx 添加對(duì)https的支持:①. 在ssl證書位置下載證書蜜葱,會(huì)有兩個(gè)文件 xxx.pem, xxx.key,在服務(wù)器nignx目錄下的conf目錄新建cert目錄耀石,將兩個(gè)文件拷貝進(jìn)去牵囤,修改conf下nginx.conf的配置
# HTTPS server
server {
    listen       443 ssl;
    server_name  api.zuo11.com;

    ssl_certificate     cert\3391782_api.zuo11.com.pem;
    ssl_certificate_key cert\3391782_api.zuo11.com.key;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    # 注釋掉默認(rèn)的加密方式
    # ssl_ciphers  HIGH:!aNULL:!MD5;
    # ssl_prefer_server_ciphers  on;

    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;  #使用此加密套件。
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;   #使用該協(xié)議進(jìn)行配置滞伟。
    ssl_prefer_server_ciphers on;

    location / {
        # root   html;
        # index  index.html index.htm;
        proxy_pass http://127.0.0.1:9000;
    }
}

#2020/03/07 周六

#nginx 中文路徑404的問題

在mac本地調(diào)試時(shí)揭鳞,都是ok的,部署到windows服務(wù)器上后時(shí)梆奈,發(fā)現(xiàn)一個(gè)圖片出現(xiàn)了404的問題野崇,最開始以為是緩存的問題,清了緩存后還是404亩钟。這張圖片是中文路徑乓梨,之前全部用的是英文的钥弯,沒發(fā)現(xiàn)這個(gè)問題。試了下英文的圖片鏈接是ok的督禽。百度了下,發(fā)現(xiàn)確實(shí)有這種問題总处。是nginx設(shè)置的編碼與操作系統(tǒng)的編碼不一致的問題狈惫。

# linux查看電腦默認(rèn)編碼
echo  $LANG
# zh_CN.UTF-8

# windows下查看默認(rèn)字符編碼
chcp
# 如果顯示 活動(dòng)代碼頁 936 表示GBK編碼  我的服務(wù)器就是這個(gè)編碼,修改了nginx charset utf-8;沒效果
# 65001 表示utf-8

# 設(shè)置字符編碼鹦马,但發(fā)現(xiàn)只在當(dāng)前控制臺(tái)生效胧谈,重新開一個(gè)就沒了。
chcp 65001

# 有個(gè)修改注冊(cè)表的方法:不知道是否可行荸频,但怕影響服務(wù)器的其它服務(wù)菱肖,還是算了,改英文名比較穩(wěn)旭从。稳强。。和悦。
# https://blog.csdn.net/yangzhong0808/article/details/79012628?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

參考:windows下cmd命令行顯示UTF8字符設(shè)置(CHCP命令)(opens new window)

#Invalid character in header content ["Content-Disposition"]

在koa中退疫,如果Content-Disposition里設(shè)置文件名有中文會(huì)提示錯(cuò)誤,需要用類似 encodeURIComponent 轉(zhuǎn)碼的函數(shù)轉(zhuǎn)碼后才行

const fileName = encodeURIComponent('這是一個(gè)文件') // 需要先轉(zhuǎn)碼才行
ctx.set({
  'Content-Type': 'application/x-tar',
  'Content-Disposition': `attachment; filename="${fileName}.tar"`
})

#2020/03/03 周二

#github Badge 與npm 徽章圖片生成

在寫readme時(shí)鸽素,最開始一般會(huì)貼一些徽章圖片褒繁,比如 build passing,license MIT 等馍忽,這些都是引入的圖片

badge徽章圖片.png
// 上圖對(duì)應(yīng)的三個(gè)徽章圖片
![version-v0.2.0](https://img.shields.io/badge/version-v0.2.0-yellow.svg) 
![build-passing](https://img.shields.io/badge/build-passing-green.svg) 
![license-MIT](https://img.shields.io/badge/license-MIT-green.svg) 
// 發(fā)現(xiàn)規(guī)律沒棒坏,更改后面的參數(shù),就可以生成不同的圖片

// 比如
https://img.shields.io/badge/JAVA-1.8+-green.svg

npm 徽章圖片遭笋,主要適用于npm包坝冕,顯示npm包的一些信息

// 文檔 https://www.npmjs.com/package/npm-badge
// zuo-blog npm包使用示例,只需要把對(duì)應(yīng)的npm 包名稱修改即可
[![NPM](https://nodei.co/npm/zuo-blog.png)](https://npmjs.org/package/zuo-blog)

#個(gè)人小程序主體可以做什么

目前小程序名稱變得很嚴(yán)格坐梯,只要包含稍微通用點(diǎn)的關(guān)鍵字徽诲,比如 "管理",都會(huì)要求上傳手持身份證照片吵血,且要有對(duì)應(yīng)的商標(biāo)證書谎替。但貌似商標(biāo)申請(qǐng)需要1000,且審批時(shí)間需要1年多... 太難了蹋辅。而且個(gè)人小程序能做的東西越來越少了钱贯。

參考:個(gè)人主體小程序開放的服務(wù)類目 - 微信開放文檔(opens new window)

#前端pc web獲取時(shí)間是不準(zhǔn)確的

我們?cè)?new Date() 時(shí),如果是在pc端侦另,電腦時(shí)間不對(duì)秩命,獲取的時(shí)間也會(huì)不對(duì)尉共。如果需要記錄時(shí)間,應(yīng)該發(fā)送請(qǐng)求給后端弃锐,讓后端計(jì)算時(shí)間袄友。依賴服務(wù)器時(shí)間

修改本地時(shí)間后,用 new Date() 獲取時(shí)間霹菊,如下圖會(huì)是錯(cuò)誤的時(shí)間

修改本地時(shí)間后獲取時(shí)間.png

#2020/03/02 周一

#瀏覽器tab頁切換時(shí)更改標(biāo)題

當(dāng)用戶點(diǎn)擊了瀏覽器其他tab頁離開頁面剧蚣,或者從其他tab頁進(jìn)入當(dāng)前頁,都會(huì)觸發(fā)visibilitychange事件旋廷,根據(jù)docuemnt.hidden可以判斷是否離開或回來鸠按,我們可以修改標(biāo)題達(dá)到可視化的一個(gè)效果

// 實(shí)現(xiàn)tab間切換時(shí),隱藏頁面title改變功能
// JS高程3 Page Visibility API(頁面可見性API)
// 參考:https://www.yuque.com/guoqzuo/js_es6/nocthb#0cf7a8b7
var title = document.title;
document.addEventListener('visibilitychange', function (event) {
  document.title =  document.hidden ? '~ 你快回來 ~ ' : title
  if (document.hidden) {
    // 做一些暫停操作
  } else {
    // 開始操作
  }
}, false)

#網(wǎng)頁中網(wǎng)絡(luò)異橙牡猓或網(wǎng)絡(luò)正常時(shí)動(dòng)態(tài)提示

監(jiān)聽頁面的online和offline事件目尖,顯示或隱藏對(duì)應(yīng)的信息

// 當(dāng)網(wǎng)絡(luò)狀態(tài)發(fā)生改變時(shí)(有網(wǎng) => 無網(wǎng),無網(wǎng) => 有網(wǎng)),提示信息
// JS高程3 離線檢測
// 參考: https://www.yuque.com/guoqzuo/js_es6/sp2k81#244d3090
let errorMsgNode // 用來移除錯(cuò)誤信息節(jié)點(diǎn)
window.ononline = function(event) {
  errorMsgNode && document.body.removeChild(errorMsgNode)
  message('success', '網(wǎng)絡(luò)已連接', 3000)
}
window.onoffline = function(event) {
  message('error', '網(wǎng)絡(luò)已斷開')
}
/**
 * 為了顯示網(wǎng)絡(luò)信息扎运,專門寫了個(gè)小tips提示函數(shù)瑟曲,在頂部顯示信息
 * @param {}} type 文字顏色 error 為紅色,其他為綠色
 * @param {*} msg 顯示信息
 * @param {*} sec 如果有傳入時(shí)間豪治,sec秒后關(guān)閉提示
 */
function message(type, msg, sec) {
  let color = type === 'error' ? 'red' : 'green'
  let cssArr = [
    'position:fixed;top:8px;left:50%;z-index:9999999;',
    'transform:translateX(-50%);padding:5px 10px;background:#fff;'
  ]
  let htmlStr = `
    <div style="${cssArr.join('')}color:${color}">${msg}</di>
  `
  let node = document.createElement('div')
  node.innerHTML = htmlStr
  document.body.appendChild(node)
  if (Number.isInteger(sec) && sec > 0) {
    setTimeout(() => {
      document.body.removeChild(node)
    }, sec)
  } else {
    // 錯(cuò)誤信息测蹲,一直提示,需要設(shè)置到變量里鬼吵,等網(wǎng)絡(luò)連接上時(shí)移除
    errorMsgNode = node
  }
}

#頁面滾動(dòng)比例監(jiān)聽實(shí)現(xiàn)

監(jiān)聽頁面的scroll事件扣甲,整個(gè)滾動(dòng)距離為 document.documentElement.scrollHeight - window.innerHeight,當(dāng)前scrollTop除以整個(gè)滾動(dòng)距離齿椅,就是頁面的百分比琉挖,向body掛載兩個(gè)div來顯示進(jìn)度信息

// 頁面滾動(dòng)比例監(jiān)聽
// posTop 頂部類似阮一峰ES6網(wǎng)頁的滾動(dòng)進(jìn)度條
// pos 右下角滾動(dòng)百分比
// JS高程3 - UI事件 scroll事件
// https://www.yuque.com/guoqzuo/js_es6/elgng1#e38771e5
let htmlStr = `
  <div id="posTop" style="position: fixed;top:0;height:2px;background: #25b864;z-index:999999;"></div>
  <div id="pos" style="display:none;position:fixed;bottom: 100px;right:20px;padding:10px;background: #25b864;color:white;width:40px;text-align: center;border-radius:5px;"></div>
`
let eleNode = document.createElement('div')
eleNode.innerHTML = htmlStr
document.body.appendChild(eleNode)

window.addEventListener('scroll', function(e) {
  let scrollTop = document.documentElement.scrollTop;
  let total = document.documentElement.scrollHeight - window.innerHeight;
  let persentage = parseInt(scrollTop/total*100);
  // console.log(scrollTop);  

  document.getElementById('pos').style.display = scrollTop === 0 ? 'none' : 'block';
  document.getElementById('pos').innerHTML = `${persentage}%`;
  document.getElementById('posTop').style.width = `${persentage}%`;
}, false)

#復(fù)制內(nèi)容后,在內(nèi)容中插入作者及當(dāng)前文章信息

監(jiān)聽body里的copy事件涣脚,然后用 document.getSelection()獲取內(nèi)容示辈,追加內(nèi)容后,再使用event.clipboardData.setData像粘貼板里寫入內(nèi)容

// 操作粘貼板
// JS高程3 表單腳本 操作粘貼板
// https://www.yuque.com/guoqzuo/js_es6/ubpn7k#8482e7c5
document.body.oncopy = function(event) {
  console.log('copy', event);
  // 獲取copy的內(nèi)容
  // console.log(document.getSelection().toString());
  // 在copy內(nèi)容里加入信息
  var msg = `
-----------------------------
標(biāo)題:${document.title}
鏈接:${location.href}
作者:guoqzuo (http://github/zuoxiaobai)
  `
  event.clipboardData.setData('text/plain', `${document.getSelection().toString()} ${msg}`);
  event.preventDefault();
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遣蚀,一起剝皮案震驚了整個(gè)濱河市矾麻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芭梯,老刑警劉巖险耀,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異玖喘,居然都是意外死亡甩牺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門累奈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贬派,“玉大人急但,你說我怎么就攤上這事「惴Γ” “怎么了波桩?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長请敦。 經(jīng)常有香客問我突委,道長,這世上最難降的妖魔是什么冬三? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮缘缚,結(jié)果婚禮上勾笆,老公的妹妹穿的比我還像新娘。我一直安慰自己桥滨,他們只是感情好异旧,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布振劳。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垒拢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天楞泼,我揣著相機(jī)與錄音领追,去河邊找鬼。 笑死唬血,一個(gè)胖子當(dāng)著我的面吹牛望蜡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拷恨,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼脖律,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了腕侄?” 一聲冷哼從身側(cè)響起小泉,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冕杠,沒想到半個(gè)月后微姊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡分预,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年柒桑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片噪舀。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡魁淳,死狀恐怖飘诗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情界逛,我是刑警寧澤昆稿,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站息拜,受9級(jí)特大地震影響溉潭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜少欺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一喳瓣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赞别,春花似錦畏陕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至崎页,卻和暖如春鞠绰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背飒焦。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工蜈膨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人牺荠。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓丈挟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親志电。 傳聞我的和親對(duì)象是個(gè)殘疾皇子曙咽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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