2018-01-30

[喜大普奔,开源地址,请猛戳我](https://github.com/KuiShang/blog-manage)[TOC]## 1 登录 登录常见验证方式是token验证, 目前打算暂时用session验证 以后有时间研究token登录,并添加第三方登录## 2 css变量的处理//TODO: 一键换肤,白天黑夜模式 先占坑 颜色变量不要写死在单独某一个组件里面,方便以后统一换风格,可以参考element 等ui库![](http://images2017.cnblogs.com/blog/821507/201712/821507-20171217165445624-812150452.png)## 3 数据接口处理 a 首先所有的接口地址写在一个文件中,,切url接口地址最好不要写死,这样有两个好处 第一 方便查找我们所有用到的接口 第二 后台接口便于修改,比如初期阶段后台接口可能较少,访问直接以 '/login' '/entry' 这样的形式访问,等以后台想把某一部分用户登录相关的接口 访问时统一在前面加上’/v1' 如果我们接口调用散落在各个文件里那就非常难以修改![](http://images2017.cnblogs.com/blog/821507/201712/821507-20171217165904296-981797936.png) b 利用 NODE_ENV 区分 当前的 baseUrl 当前前端webpackdevserver地址为 127.0.0.1:8080 例如 开发环境时我的 baseUrl 为 ‘’,所有接口的访问的为当前ip当前接口,模拟数据可以用 axios-mock-adapter (与axios配合简单方便) --- 这是模拟数据方式一 这种数据访问地址为 127.0.0.1:8080 -> 127.0.0.1:8080![](http://images2017.cnblogs.com/blog/821507/201712/821507-20171217170952202-668042597.png) 例如 我想用json-server,或者express 自己起一个server 做模拟数据服务器,地址为127.0.0.1:3005 开发环境时我的 baseUrl 则就改为 ‘127.0.0.1:3005 ’, 这种数据访问地址为 127.0.0.1:8080 -> 127.0.0.1:3005 存在跨域 所以需要在webpack-dev-config.js中加入 ````proxyTable: { '/': { target: 'http://127.0.0.1:3005', }}```` 也就是将所以8080的访问 代理到3005上 ##### 小总结 so~ axios-mock-adapter 优点 使用简单 不存在跨域 缺点 不能动态根据前端传递参数不同返回不同结果,自己起的模拟服务器当然你自己想怎么干就怎么干了,上天都没人管你~![](http://images2017.cnblogs.com/blog/821507/201712/821507-20171217170358327-661291295.png) c 利用axios的全局配置功能, 添加baseurl, -- 可以方便修改根路径 添加请求、响应拦截器 首先这是符合 统一入口思想的,very good~~~ 如此以来我们可以对所有的请求统一处理 比如打印请求日志,过滤关键key,等等 对统一返回也可以 根据某些错误码进行全局warn处理![](http://images2017.cnblogs.com/blog/821507/201712/821507-20171217170602889-1544507955.png)## 4一个逗号引发的血案~![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180124145629569-195284115.png) 错误很清楚的写明了 在setAttribute 时候 key 填入的是逗号,经过纠结的一一对比最终发现这个问题是 在元素的属性上 有逗号忘记了删除![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180124145912319-1558749930.png) 你一眼就能看到吗? 如果能看到 恭喜你 ,不用(像我一样)再走弯路~ 引发原因是当初参照的其他template模板用的是 pug语法,其中每个属性是用逗号隔开的 而我们这里是html语法 都好一定要删除,否则 vue会当做属性填充,切记切记## 5再看父子组件的传值(这一条之前理解稍微有误,可以跳过)我们都知道通过props可以由父组件给子组件传递值

----  以下理解有误,留作历史吧,大家可以不看 ~~**需要注意的是以上只适合传输字符串  而不能传输对象!**~~~~**需要注意的是以上只适合传输字符串 而不能传输对象!**~~~~如果你想把一个对象的所有属性作为 prop 进行传递,可以使用不带任何参数的 v-bind (即用 v-bind 而不是 v-bind:prop-name)。例~~~~如,已知一个 todo 对象:~~    todo: {      text: 'Learn Vue',      isComplete: false    }    ~~然后:~~~~将等价于:~~>~~子类接受属性时:~~props: ['text', 'is-complete']~~阔是!如果父组件data里面有一个目录属性 是数组结构~~    data () {        return {            cagalogs: [            {},            {},            {}            ]        }    }~~此时,我们将无法通过父组件传递数据过去,~~~~出现这种情况的场景是,管理系统 博客展示页面 展示了有多少个目录,已经获取了一遍目录数据, 在新增文章时候还会弹出编辑组~~~~件,此时让需要目录数据~~这种情况下的解决方案:* 通过 props  -----------> 走不通* 通过 vuex --------------> 不推荐,因为只是两个组件使用,不想都放到全局,避免常驻内存* 存放到 localstorage + mixin --------> 暂时采用此方案mixin.js    import urls from '@/config/urls    import {storageKey, setStorage, getStorage} from '@/utils/storage'    export default {      data () {        return {          catalogs: []        }      },      methods: {        async getCatalogs () {          let catalogs = getStorage(storageKey.CATALOGS)          if (catalogs) {            this.catalogs = catalogs            return          }          const res = await this.axios.get(urls.catalogList)          if (res.data.status === 0) {            setStorage(storageKey.CATALOGS, res.data.data)            this.catalogs = res.data.data          }        }      }    }~~虽然最终数据都是取的 localstorage 下的 数据 , 但 两个组件实际上是 自己维护了自己的 catalogs 这个 属性。~~# 前台博客记录## 如何找到其他网站的源码实现主界面封面部分参考了 [搜车大无线团队博客](http://f2e.souche.com/blog/),其中有一个功能 封面 有一个下箭头,点击一下 实现滚屏到博客正文![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180119093857678-1562042516.png)----直观发现此处是通过href锚点实现滚动,然而自己实现时发现这样并没有滚动动画,但是他们是怎么做到的呢,开始我一直以为肯定是用了某个css3动画实现,但是根本找不到任何css相关的样式----![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180119093934224-1771605071.png)----如何确定是不是用js实现的呢?----![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180119094347771-397359382.png)----如图点击js便可跳转到相应js文件,并发现了用animate的地方,由此我们得出了原来此处是用js,根本和css没有半毛线关系~----## 如何找到其他网站的源码实现2----不巧的是 博主还算是一个发(没)散(头)思(没)维(闹)的人,又去了[饿了么](http://element-cn.eleme.io/#/zh-CN/component/steps) 研究一下 回到顶部功能是如何实现的。----![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180119094941209-543342861.png)----这次我们轻车熟路的就找到了源码,只是不幸这次点进去是vue的源码,所以并没有什么卵用, 我们 发现 这个div 的类名 为 ***page-component-up*** 嗯,我们有理由相信 源码是通过给这个类名添加点击事件实现的,(谁给你的自信?)so~ ,我们从github 下载[element 源码](https://github.com/ElemeFE/element), vscode 打开,全文搜索(ctrl shift f),这个类名, 在 component.tpl 文件下找到了源码 欧耶~   .page-component__scroll {

    height: calc(100% - 80px);

    margin-top: 80px;

    .el-scrollbar__wrap {

      overflow-x: auto;

    }

  }

  .page-component {

    box-sizing: border-box;

    height: 100%;


    &.page-container {

      padding: 0;

    }

    .page-component__nav {

      width: 240px;

      position: fixed;

      top: 0;

      bottom: 0;

      margin-top: 80px;

      transition: padding-top .3s;

      .el-scrollbar__wrap {

        height: 100%;

      }

      &.is-extended {

        padding-top: 0;

      }

    }

    .side-nav {

      height: 100%;

      padding-top: 50px;

      padding-bottom: 50px;

      padding-right: 0;

      & > ul {

        padding-bottom: 50px;

      }

    }

    .page-component__content {

      padding-left: 270px;

      padding-bottom: 100px;

      box-sizing: border-box;

    }

    .content {

      padding-top: 50px;

      > {

        h3 {

          margin: 55px 0 20px;

        }

        table {

          border-collapse: collapse;

          width: 100%;

          background-color: #fff;

          font-size: 14px;

          margin-bottom: 45px;

          line-height: 1.5em;

          strong {

            font-weight: normal;

          }

          td, th {

            border-bottom: 1px solid #d8d8d8;

            padding: 15px;

            max-width: 250px;

          }

          th {

            text-align: left;

            white-space: nowrap;

            color: #666;

            font-weight: normal;

          }

          td {

            color: #333;

          }

          th:first-child, td:first-child {

            padding-left: 10px;

          }

        }

        ul:not(.timeline) {

          margin: 10px 0;

          padding: 0 0 0 20px;

          font-size: 14px;

          color: #5e6d82;

          line-height: 2em;

        }

      }

    }

    .page-component-up {

      background-color: #fff;

      position: fixed;

      right: 100px;

      bottom: 150px;

      size: 40px;

      border-radius: 20px;

      cursor: pointer;

      transition: .3s;

      box-shadow: 0 0 6px rgba(0,0,0, .12);

      i {

        color: #409EFF;

        display: block;

        line-height: 40px;

        text-align: center;

        font-size: 18px;

      }

      &.hover {

        opacity: 1;

      }

    }

    .back-top-fade-enter,

    .back-top-fade-leave-active {

      transform: translateY(-30px);

      opacity: 0;

    }

  }

  @media (max-width: 768px) {

    .page-component {

      .page-component__nav {

        width: 100%;

        position: static;

        margin-top: 0;

      }

      .side-nav {

        padding-top: 0;

        padding-left: 50px;

      }

      .page-component__content {

        padding-left: 10px;

        padding-right: 10px;

      }

      .content {

        padding-top: 0;

      }

      .content > table {

        overflow: auto;

        display: block;

      }

      .page-component-up {

        display: none;

      }

    }

  }

  import bus from '../../bus';

  import navsData from '../../nav.config.json';

  import throttle from 'throttle-debounce/throttle';

  export default {

    data() {

      return {

        lang: this.$route.meta.lang,

        navsData,

        hover: false,

        showBackToTop: false,

        scrollTop: 0,

        showHeader: true,

        componentScrollBar: null,

        componentScrollBoxElement: null

      };

    },

    watch: {

      '$route.path'() {

        // 触发伪滚动条更新

        this.componentScrollBox.scrollTop = 0;

        this.$nextTick(() => {

          this.componentScrollBar.update();

        });

      }

    },

    methods: {

      renderAnchorHref() {

        if (/changelog/g.test(location.href)) return;

        const anchors = document.querySelectorAll('h2 a,h3 a');

        const basePath = location.href.split('#').splice(0, 2).join('#');

        [].slice.call(anchors).forEach(a => {

          const href = a.getAttribute('href');

          a.href = basePath + href;

        });

      },

      goAnchor() {

        if (location.href.match(/#/g).length > 1) {

          const anchor = location.href.match(/#[^#]+$/g);

          if (!anchor) return;

          const elm = document.querySelector(anchor[0]);

          if (!elm) return;

          setTimeout(_ => {

            this.componentScrollBox.scrollTop = elm.offsetTop;

          }, 50);

        }

      },

      toTop() {

        this.hover = false;

        this.showBackToTop = false;

        this.componentScrollBox.scrollTop = 0;

      },

      handleScroll() {

        const scrollTop = this.componentScrollBox.scrollTop;

        this.showBackToTop = scrollTop >= 0.5 * document.body.clientHeight;

        if (this.showHeader !== this.scrollTop > scrollTop) {

          this.showHeader = this.scrollTop > scrollTop;

        }

        if (scrollTop === 0) {

          this.showHeader = true;

        }

        if (!this.navFaded) {

          bus.$emit('fadeNav');

        }

        this.scrollTop = scrollTop;

      }

    },

    created() {

      bus.$on('navFade', val => {

        this.navFaded = val;

      });

      window.addEventListener('hashchange', () => {

        if (location.href.match(/#/g).length < 2) {

          document.documentElement.scrollTop = document.body.scrollTop = 0;

          this.renderAnchorHref();

        } else {

          this.goAnchor();

        }

      });

    },

    mounted() {

      this.componentScrollBar = this.$refs.componentScrollBar;

      this.componentScrollBox = this.componentScrollBar.$el.querySelector('.el-scrollbar__wrap');

      this.throttledScrollHandler = throttle(300, this.handleScroll);

      this.componentScrollBox.addEventListener('scroll', this.throttledScrollHandler);

      this.renderAnchorHref();

      this.goAnchor();

      document.body.classList.add('is-component');

    },

    destroyed() {

      document.body.classList.remove('is-component');

    },

    beforeDestroy() {

      this.componentScrollBox.removeEventListener('scroll', this.throttledScrollHandler);

    }

  };

-------# 后台 node api 系统## 1如何使用es6语法1 入口文件引入bable-core![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180127141050209-143780521.png)2 在.babelrc 如下配置,经本人测试,stage-3 如果不配置 则 【扩展运算符】使用会报错![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180127141201975-379915176.png)3 安装相关依赖![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180127141509334-1281137278.png)## 2继承使用问题 this问题    在类中 如果有需要用到内部this 的方法中  需要 在 constructor 中 通过bind 应绑定 this,    因为这些类的方法的调用形式为 如下图二调用,因此 若想用this,需要在constructure中 进行 硬绑定图一,control对象声明![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180127141646553-733500642.png)图二 路由调用 相应的control对象的方法的引用 ![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180127141931709-66667539.png)## 3通过 vscode 进行断点调试网上最常见的三种查询方法1 node-inspector 之前尝试过 好像最终可以chrome 进行断点, 但是还是偶尔失败,且麻烦  所以 舍弃2  好像还可以通过 --xxx  加类似什么参数来着, 但是也没成功  所以 舍弃3 webstorm 还是算了吧……4 我们说一下 用vscode 调试默认情况下直接按 f5 就会呼出调试界面,直接选择node 即可,也可通过配置,默认情况下 入口是 app.js我们根据需要修改即可。![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180127152132397-818398825.png)## 4给 mongoose find 命令 返回的 数据 添加额外属性的两种方式mongoose find 命令 返回的 数据结构如图![](http://images2017.cnblogs.com/blog/821507/201801/821507-20180129125916437-438628837.png)如果我们想在find命令后返回的对象里面添加其定义属性,比如 动态的给每一个对象添加一个 uid属性, 我们直接给对象添加是**无效的,**即使当时你手动添加上打印出来可以看到,但是返回到客户端 却没有这个属性因为mongoose内部会检查你要添加的这个属性是否是在scheme上,一说可以通过 strict: false 让查询出的结果可修改,不过测试发现没有什么卵用愿意是  mongoose 返回的 对象 其实实在 当前对象的  _doc 属性 下面**方式一 粗暴添加**所以  我们可以 通过 给对对象的_doc属性下的对象添加自定义属性即可**方式二 温柔添加**mongoose 提供啦 toObject()方法 也可以添加最终的代码类似于:    var model = obj.toObject();    model.isBorrow = false;    cb(null, model);    ## 5 循环+异步引起的**大**坑场景描述查询文章列表接口需要返回的数据格式如下    {                    "id": "0920892e-1512-401a-994e-5406a14aca0b",                    "title": "Vue2 + Nodejs  + WebSocket 完成你画我猜多人在线游戏",                    "summary": "使用 websocket + vue2 即可完成一个很有意思的在线游戏作品。 你画我猜,相信大家对这个游戏都很熟悉。 我用Vue2 + mint-ui + nodejs + websocket 实现了你画我猜这个游戏。 建议移动端打开效果更佳(可扫下方二维码),PC端需要使用谷歌开发者模式,然后使用移动调试工具,才可以正常使用(主要是一些touch事件,pc不支持)。  大家可以拉上一两个人,来开个房间试试看,体验体验效果。 http://yd.diamondfsd.com  主要实现了以下这些功能  大厅功能  个人信息显示 顶部显示个人昵称,可以修改 暂时不支持上传头像,头像用昵称第一个",                    "createTime": 1487680940000,                    "updateTime": 1487686388000,                    "catalogId": "1d16334c-3231-4232-9adc-e57e5d74552e",                    "banner": "",                    "tagNames": "你画我猜手机游戏",                    "catalogName": "技术分享",                    "tags": [{                        "id": "a0997aea-2a58-431c-8dad-f88843515587",                        "name": "你画我猜手机游戏"                    }其中 __catalogName__ 这个字段

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容

  • 早上会议室一个上午针对苹果爸爸退回APP1.5.2版发来的邮件,开始分析自检。 邮件内容: Guideline 2...
    公羽辰阅读 536评论 1 0
  • 第三次周会议记录 时间:2018年1月26日6:00-7:00 地点:YY81080645,子频道:G161期90...
    涂艳珍阅读 286评论 0 0
  • 前天和几个在冷库上班的老乡,在食堂喝酒。 其中一个年长的,多喝了几杯就开始述说自己的故事,工作了多少年,工资依然...
    k承龙阅读 758评论 0 51
  • 作业可真特么傻逼,妈的真够烦的
    你再也不是我心中的你了阅读 151评论 0 0
  • 千万不要对自己的恶习产生顺流而下的心态,这样只会对自己的恶习进行强化;每天早上起床总要在被窝里赖一下,想着再睡一分...
    追墨残梦阅读 190评论 0 0