子羽

子羽 查看完整档案

深圳编辑  |  填写毕业院校深圳星火电子  |  高级前端工程师 编辑 47.96.19.54:8080/book_webapp/index.html 编辑
编辑

You jump, I jump

个人动态

子羽 收藏了文章 · 2020-01-13

css scrollbar样式设置

一 前言

在CSS 中,如果我们在块级容器上设置了属性:

overflow:scroll /* x y 方向都会*/
或者
overflow-x:scroll /*只是x方向*/
或者
overflow-y:scroll  /*只是y方向*/

当块级内容区域超出块级元素范围的时候,就会以滚动条的形式展示,你可以滚动里面的内容,里面的内容不会超出块级区域范围。
有时候我们需要自定义滚动条的样式,比如一开始就它显示,比如想改变滚动条的颜色,设置轨道的样式等,那么这篇文章就是为你准备的。

二 正文

1.认识滚动条

图片描述

设置scrollbar的为CSS伪元素,对应上图的数字:

::-webkit-scrollbar              { /* 1 */ }
::-webkit-scrollbar-button       { /* 2 */ }
::-webkit-scrollbar-track        { /* 3 */ }
::-webkit-scrollbar-track-piece  { /* 4 */ }
::-webkit-scrollbar-thumb        { /* 5 */ }
::-webkit-scrollbar-corner       { /* 6 */ }
::-webkit-resizer                { /* 7 */ }

属性介绍:

::-webkit-scrollbar    //滚动条整体部分
::-webkit-scrollbar-button   //滚动条两端的按钮
::-webkit-scrollbar-track   // 外层轨道
::-webkit-scrollbar-track-piece    //内层轨道,滚动条中间部分(除去)
::-webkit-scrollbar-thumb //滚动条里面可以拖动的那个
::-webkit-scrollbar-corner   //边角
::-webkit-resizer   ///定义右下角拖动块的样式

2.设置样式

demo
进入页面,打开控制台工具,选中其中一个样式,就能看到该样式的CSS源码。

/*定义滚动条高宽及背景
 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar
{
    width:16px;
    height:16px;
    background-color:#F5F5F5;
}
/*定义滚动条轨道
 内阴影+圆角*/
::-webkit-scrollbar-track
{
    -webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.3);
    border-radius:10px;
    background-color:#F5F5F5;
}
/*定义滑块
 内阴影+圆角*/
::-webkit-scrollbar-thumb
{
    border-radius:10px;
    -webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3);
    background-color:#555;
}

图片描述

任何对象都可以设置:边框、阴影、背景图片等等,创建的滚动条任然会按照操作系统本身的设置来完成其交互的行为。下面的伪类可以应用到上面的伪元素中。

:horizontal//适用于任何水平方向上的滚动条
:vertical//适用于任何垂直方向的滚动条
:decrement//适用于按钮和轨道碎片。表示递减的按钮或轨道碎片,例如可以使区域向上或者向右移动的区域和按钮
:increment//适用于按钮和轨道碎片。表示递增的按钮或轨道碎片,例如可以使区域向下或者向左移动的区域和按钮
:start//适用于按钮和轨道碎片。表示对象(按钮轨道碎片)是否放在滑块的前面
:end //适用于按钮和轨道碎片。表示对象(按钮轨道碎片)是否放在滑块的后面
:double-button//适用于按钮和轨道碎片。判断轨道结束的位置是否是一对按钮。也就是轨道碎片紧挨着一对在一起的按钮。
:single-button//适用于按钮和轨道碎片。判断轨道结束的位置是否是一个按钮。也就是轨道碎片紧挨着一个单独的按钮。
:no-button//表示轨道结束的位置没有按钮。
:corner-present//表示滚动条的角落是否存在。
:window-inactive//适用于所有滚动条,表示包含滚动条的区域,焦点不在该窗口的时候。

用法举例:

::-webkit-scrollbar-track-piece:start {
   /* Select the top half (or left half) or scrollbar track individually */
}

::-webkit-scrollbar-thumb:window-inactive {
   /* Select the thumb when the browser window isn't in focus */
}

::-webkit-scrollbar-button:horizontal:decrement:hover {
   /* Select the down or left scroll button when it's being hovered by the mouse */
}

3.IE浏览器
兼容IE的参考链接:https://www.cnblogs.com/koley...

图片描述

图片描述

三 后记

Chrome能很好的支持自定义滚动条,其它的浏览器在不同程度上支持自定义滚动条样式。
参考文章:http://blog.csdn.net/cysear/a...

查看原文

子羽 回答了问题 · 2019-12-26

解决vue用axios时报错:Cannot read property 'protocol' of undefined!

除了上面的原因,发现还有一个原因也会报这个错,就是当url是undefined的时候

关注 10 回答 7

子羽 赞了回答 · 2019-12-24

解决vue-router嵌套问题

你这写的都是同级路由,怎么会嵌套呢?

{
  path: '/bgManagement',
  name: 'bgManagement',
  components: {
    default: bgManagement,
  },
  children: [
    {
      path: '/bgManagement/monitorBallPdt',
      name: 'monitorBallPdt',
      components: {
        'management': monitorBallPdt,
      },
    },
    {
      path: '/bgManagement/monitorPolice',
      name: 'monitorPolice',
      components: {
        'management': monitorPolice,
      },
    },
  ],
},

试下这样写

关注 1 回答 1

子羽 提出了问题 · 2019-12-23

解决vue-router嵌套问题

/bgManagement/monitorBallPdt对应的页面中的<router-view>未匹配到,页面显示为空,主要代码如下:

App.vue

<template>
  <div id="app">
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

<style lang="less">
html,
body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  #app {
    width: 100%;
    height: 100%;
  }
}
</style>
router.js
import Vue from 'vue'
import Router from 'vue-router'
import index from '../views/index.vue'
import gisPlatform from '../views/gisPlatform.vue'
import bgManagement from "@/views/bgManagement/index"
import monitorBallPdt from "@/views/bgManagement/monitorBallPdt/monitorBallPdt"
import monitorPolice from "@/views/bgManagement/monitorPolice/monitorPolice"

Vue.use(Router)

export default new Router({
  mode: 'hash',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'index',
      components: {
        default: index
      }
    },
    {
      path: '/gisPlatform',
      name: 'gisPlatform',
      components: {
        default: gisPlatform
      }
    },
    {
      path: '/bgManagement/monitorBallPdt',
      name: 'bgManagement',
      components: {
        default: bgManagement,
        "management": monitorBallPdt
      }
    },
    {
      path: '/bgManagement/monitorPolice',
      name: 'monitorPolice',
      components: {
        default: bgManagement,
        "management": monitorPolice
      }
    }
  ]
})
bgManagement/index.vue
<template>
    <div id="bgm">
        <el-container style="height: 100%;">
            <el-header style="background-color:#252525;">
                <banner></banner>
            </el-header>
            <el-container>
                <el-aside width="200px" style="background-color: #35373F;">
                    <el-menu
                        :default-active="indexActive"
                        @select="select"
                        class="el-menu-vertical-demo"
                        background-color="#35373F"
                        text-color="#fff"
                        active-text-color="#fff"
                        :router="true"
                    >
                        <el-menu-item index="/bgManagement/monitorBallPdt">
                            <i class="iconfont iconerji-yingyonggailan"></i>
                            <span slot="title">绑定人员</span>
                        </el-menu-item>
                        <el-menu-item index="/bgManagement/monitorPolice">
                            <i class="iconfont iconerji-yingyonggailan"></i>
                            <span slot="title">绑定设备</span>
                        </el-menu-item>

                    </el-menu>
                </el-aside>
                <el-main>
                    <keep-alive>
                        <router-view name="management"></router-view>
                    </keep-alive>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>

<script>
import banner from './banner'

export default {
    data(){
        return {
            indexActive: '/bgManagement/monitorBallPdt'
        }
    },
    components: {
        banner
    },
    methods: {
        
    }
}
</script>

<style lang="less" scope>
#bgm{
    width: 100%;
    height: 100%;
    .is-active{
        background-color: #009688 !important;
    }
}
</style>

关注 1 回答 1

子羽 赞了文章 · 2019-10-30

css scrollbar样式设置

一 前言

在CSS 中,如果我们在块级容器上设置了属性:

overflow:scroll /* x y 方向都会*/
或者
overflow-x:scroll /*只是x方向*/
或者
overflow-y:scroll  /*只是y方向*/

当块级内容区域超出块级元素范围的时候,就会以滚动条的形式展示,你可以滚动里面的内容,里面的内容不会超出块级区域范围。
有时候我们需要自定义滚动条的样式,比如一开始就它显示,比如想改变滚动条的颜色,设置轨道的样式等,那么这篇文章就是为你准备的。

二 正文

1.认识滚动条

图片描述

设置scrollbar的为CSS伪元素,对应上图的数字:

::-webkit-scrollbar              { /* 1 */ }
::-webkit-scrollbar-button       { /* 2 */ }
::-webkit-scrollbar-track        { /* 3 */ }
::-webkit-scrollbar-track-piece  { /* 4 */ }
::-webkit-scrollbar-thumb        { /* 5 */ }
::-webkit-scrollbar-corner       { /* 6 */ }
::-webkit-resizer                { /* 7 */ }

属性介绍:

::-webkit-scrollbar    //滚动条整体部分
::-webkit-scrollbar-button   //滚动条两端的按钮
::-webkit-scrollbar-track   // 外层轨道
::-webkit-scrollbar-track-piece    //内层轨道,滚动条中间部分(除去)
::-webkit-scrollbar-thumb //滚动条里面可以拖动的那个
::-webkit-scrollbar-corner   //边角
::-webkit-resizer   ///定义右下角拖动块的样式

2.设置样式

demo
进入页面,打开控制台工具,选中其中一个样式,就能看到该样式的CSS源码。

/*定义滚动条高宽及背景
 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar
{
    width:16px;
    height:16px;
    background-color:#F5F5F5;
}
/*定义滚动条轨道
 内阴影+圆角*/
::-webkit-scrollbar-track
{
    -webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.3);
    border-radius:10px;
    background-color:#F5F5F5;
}
/*定义滑块
 内阴影+圆角*/
::-webkit-scrollbar-thumb
{
    border-radius:10px;
    -webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3);
    background-color:#555;
}

图片描述

任何对象都可以设置:边框、阴影、背景图片等等,创建的滚动条任然会按照操作系统本身的设置来完成其交互的行为。下面的伪类可以应用到上面的伪元素中。

:horizontal//适用于任何水平方向上的滚动条
:vertical//适用于任何垂直方向的滚动条
:decrement//适用于按钮和轨道碎片。表示递减的按钮或轨道碎片,例如可以使区域向上或者向右移动的区域和按钮
:increment//适用于按钮和轨道碎片。表示递增的按钮或轨道碎片,例如可以使区域向下或者向左移动的区域和按钮
:start//适用于按钮和轨道碎片。表示对象(按钮轨道碎片)是否放在滑块的前面
:end //适用于按钮和轨道碎片。表示对象(按钮轨道碎片)是否放在滑块的后面
:double-button//适用于按钮和轨道碎片。判断轨道结束的位置是否是一对按钮。也就是轨道碎片紧挨着一对在一起的按钮。
:single-button//适用于按钮和轨道碎片。判断轨道结束的位置是否是一个按钮。也就是轨道碎片紧挨着一个单独的按钮。
:no-button//表示轨道结束的位置没有按钮。
:corner-present//表示滚动条的角落是否存在。
:window-inactive//适用于所有滚动条,表示包含滚动条的区域,焦点不在该窗口的时候。

用法举例:

::-webkit-scrollbar-track-piece:start {
   /* Select the top half (or left half) or scrollbar track individually */
}

::-webkit-scrollbar-thumb:window-inactive {
   /* Select the thumb when the browser window isn't in focus */
}

::-webkit-scrollbar-button:horizontal:decrement:hover {
   /* Select the down or left scroll button when it's being hovered by the mouse */
}

3.IE浏览器
兼容IE的参考链接:https://www.cnblogs.com/koley...

图片描述

图片描述

三 后记

Chrome能很好的支持自定义滚动条,其它的浏览器在不同程度上支持自定义滚动条样式。
参考文章:http://blog.csdn.net/cysear/a...

查看原文

赞 106 收藏 84 评论 4

子羽 收藏了文章 · 2019-07-04

值得收藏 7 个有用JavaScript技巧

值得收藏 7 个有用JavaScript技巧

像其它语言一样,JavaScript中也可以通过一些技巧来完成一些复杂的操作. 接下来我们学习吧

数组去重

    var arr = [1, 2, 3, 3, 4];
    console.log(...new Set(arr))
    >> [1, 2, 3, 4]

数组和布尔

有时我们需要过滤数组中值为 false 的值. 例如(0, undefined, null, false), 你可能不知道这样的技巧

 var myArray = [1, 0 , undefined, null, false];
 myArray.filter(Boolean);
 >> [1]

是不是很简单, 只需要传入一个 Boolean 函数即可.

创建一个空对象

有时我们需要创建一个纯净的对象, 不包含什么原型链等等. 一般创建空对象最直接方式通过字面量 {}, 但这个对象中依然存在 __proto__ 属性来指向 Object.prototype 等等.


    let dict = Object.create(null);

    dict.__proto__ === "undefined" 

合并对象

在JavaScript中合并多个对象的需求一直存在, 比如在传参时需要把表单参数和分页参数进行合并后在传递给后端

    const page = {
        current: 1,
        pageSize: 10
    }

    const form = {
        name: "",
        sex: ""
    }

    const params = {...form, ...page};

    /*
        {
            name: "",
            sex: "",
            current: 1,
            pageSize: 10

        }
    *

利用ES6提供的扩展运算符让对象合并变得很简单.

函数参数必须

ES6中可以给参数指定默认值,确实带来很多便利. 如果需要检测某些参数是必传时,可以这么做

    const isRequired = () => { throw new Error('param is required'); };

    const hello = (name = isRequired()) => { console.log(`hello ${name}`) };

    // 这里将抛出一个错误,因为名字时必须
    hello();
    // 这也将抛出一个错误
    hello(undefined);

    // 正常
    hello(null);
    hello('David'); 

解构赋值时使用别名

解构赋值是一个非常受欢迎的JavaScript功能,但有时我们更喜欢用其他名称引用这些属性,所以我们可以利用别名来完成:


    const obj = { x: 1 };

    // Grabs obj.x as { x }
    const { x } = obj;

    // Grabs obj.x as { otherName }
    const { x: otherName } = obj;

获取查询参数

多年来,我们编写粗糙的正则表达式来获取查询字符串值,但那些日子已经一去不复返了; 现在我们可以通过 URLSearchParams API 来获取查询参数

在不使用 URLSearchParams 我们通过正则的方式来完成获取查询参数的, 如下:


  function getQueryString(name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    var r = window.location.search.substr(1).match(reg);
    return r ? r[2] : null;
  }

使用 URLSearchParams 之后:


    // 假设地址栏中查询参数是这样 "?post=1234&action=edit"

    var urlParams = new URLSearchParams(window.location.search);

    console.log(urlParams.has('post')); // true
    console.log(urlParams.get('action')); // "edit"
    console.log(urlParams.getAll('action')); // ["edit"]
    console.log(urlParams.toString()); // "?post=1234&action=edit"
    console.log(urlParams.append('active', '1')); // "?post=1234&action=edit&active=1"

相比之前使用起来更加容易了.

查看原文

子羽 发布了文章 · 2019-06-17

git使用总结


一、安装git

1.在官网下载安装包,直接安装,无需其他配置
2.安装成功后,在开始菜单或者点击鼠标右键,找到git bash,打开会看到像命令行工具一样的界面
3.执行以下命令,设置用户名和邮箱地址
git config --global user.name "Your Name"
git config --global user.email "email@example.com"


二、常用命令

1.在工作目录执行以下命令,创建git仓库
git init

2.执行以下命令,将文件添加到git仓库(.表示所有文件,也可以单独添加某个文件)
git add . or 文件目录

3.执行以下命令,将文件提交到git仓库(add可以执行多次添加,commit会统一提交)
git commit -m '提交描述文字'

4.执行以下命令,查看仓库当前状态
git status

5.执行以下命令,查看某一个具体修改了什么内容
git diff <file>

6.执行以下命令,显示从最近到最远的提交日志
git log

7.回滚版本(^:上一个版本,^^:上上一个版本,~10:之前第10个版本)
git reset --hard HEAD^

8.回滚之后恢复之前版本
git reset --hard 之前版本的id

9.查看每一次操作记录
git reflog

10.丢弃工作区的修改
git checkout -- <file>

11.把暂存区的修改撤销掉(unstage),重新放回工作区
git reset HEAD <file>

12.删除文件
git rm <file>

13.用版本库中的文件替换工作区的文件,或者恢复误删文件
git checkout -- <file>

14.将本地git仓库关联远程仓库
git remote add origin https://github.com/jaxlix/ces...

15.将本地git仓库提交到远程仓库
git push -u origin master

16.将本地git仓库修改提交到远程仓库
git push origin master

17.将远程仓库克隆到本地
git clone https://github.com/jaxlix/ces...

18.创建并切换到分支
git checkout -b 分支名称

19.创建分支
git branch 分支名称

20.切换分支
git checkout 分支名称

21.查看当前分支
git branch

22.合并指定分支到当前分支
git merge 分支名称

23.删除分支
git branch -d 分支名称


三、git多人协作的工作模式

1.保证主分支master稳定,仅在发布新版本时提交到master,开发在dev分支进行,bug处理和新功能开发在本地分支进行,完成后合并到dev分支并提交;

2.首先,可以试图用git push origin dev推送自己的修改;

3.如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

4.如果合并有冲突,则解决冲突,并在本地提交;

5.没有冲突或者解决掉冲突后,再用git push origin dev推送就能成功!

注:如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。

查看原文

赞 1 收藏 1 评论 0

子羽 回答了问题 · 2019-05-10

layuiadmin后台模板是怎么做到单页模式的

我也在找,楼主找到了吗?个人猜测是jQuery的load()方法

关注 2 回答 1

子羽 评论了文章 · 2019-05-07

vlc+video全浏览器兼容视频播放、倍速播放

一、项目起源

公司项目中需要视频播放,并且需要实现倍速播放,最重要的是需要兼容IE8,于是乎HTML5的video显然无法使用,只能另辟蹊径,查找资料最终决定使用vlc视频播放插件兼容IE,再加上video,可以实现全浏览器兼容的视频播放和倍速播放。

二、解决思路

首先H5video无法兼容低版本IE,考虑使用ActiveX视频播放插件,vlc视频播放软件有自带的ActiveX插件,安装时会自动安装插件,不过要注意的是vlc的版本必须与IE浏览器的版本一致(即如果IE是32位则必须安装32位vlc)。使用vlc解决IE的视频播放和倍速播放,其它浏览器则使用video实现。

三、解决办法

1、判断浏览器类型

// 获取浏览器类型
        function getBrowserInfo() {
            var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 
            var isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器 
            var isIE = window.ActiveXObject || "ActiveXObject" in window
            var isEdge = userAgent.indexOf("Edge") > -1; //判断是否IE的Edge浏览器
            var isFF = userAgent.indexOf("Firefox") > -1; //判断是否Firefox浏览器 
            var isSafari = userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") == -1; //判断是否Safari浏览器 
            var isChrome = userAgent.indexOf("Chrome") > -1 && userAgent.indexOf("Safari") > -1 && !isEdge; //判断Chrome浏览器 
            if (isIE) {
                var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
                reIE.test(userAgent);
                var fIEVersion = parseFloat(RegExp["$1"]);
                if (userAgent.indexOf('MSIE 6.0') != -1) {
                    return "IE6";
                } else if (fIEVersion == 7) {
                    return "IE7";
                } else if (fIEVersion == 8) {
                    return "IE8";
                } else if (fIEVersion == 9) {
                    return "IE9";
                } else if (fIEVersion == 10) {
                    return "IE10";
                } else if (userAgent.toLowerCase().match(/rv:([\d.]+)\) like gecko/)) {
                    return "IE11";
                } else {
                    return "0"
                } //IE版本过低
            } //isIE end 

            if (isFF) {
                return "FF";
            }
            if (isOpera) {
                return "Opera";
            }
            if (isSafari) {
                return "Safari";
            }
            if (isChrome) {
                return "Chrome";
            }
            if (isEdge) {
                return "Edge";
            }
        }

2、若是IE则判断是否安装vlc ActiveX插件

        function isInsalledIEVLC() {
            var vlcObj = null;
            var vlcInstalled = false;
            try {
                vlcObj = new ActiveXObject("VideoLAN.Vlcplugin.2");
                if (vlcObj != null) {
                    vlcInstalled = true
                }
            } catch (e) {
                vlcInstalled = false;
            }
            return vlcInstalled;
        }

3、若未安装则判断浏览器版本,根据版本下载对应的vlc

        // 获取浏览器32位还是64位,安装对应的vlc
        function getPlatform() {
            var agent = navigator.platform.toLowerCase();
            if (agent.indexOf("win64") >= 0 || agent.indexOf("wow64") >= 0) {
                return "win64";
            } else if(agent.indexOf("win32") >= 0 || agent.indexOf("wow32") >= 0){
                return "win32";
            }
        }

4、若是IE浏览器且已安装vlc,HTML标签如下

<embed id="vlcObj" type="application/x-vlc-plugin" pluginspage="http://www.videolan.org" width="100%" height="480" />

5、非IE浏览器使用video

        <video id="video" data-original="" controls width="100%" height="480">
            您的浏览器版本太旧,请更新版本或使用其他浏览器
        </video>

6、播放和暂停

        var useVlc = getBrowserInfo().indexOf('IE') != -1;
        var VIDEO = document.getElementById("video");
        var VLC = document.getElementById("vlcObj");
        // 播放
        function playVideo(url) {
            if(useVlc){
                url ? VLC.playlist.add(url) : "";
                VLC.playlist.play();
            }else{
                url ? VIDEO.src = url : "";
                VIDEO.networkState != 3 ?  VIDEO.play() : "";
            }
        }

        // 暂停播放
        function zanting() {
            if(useVlc){
                VLC.playlist.pause();
            }else{
                VIDEO.pause();
            }
        }

7、倍速播放

// 绑定倍速
        <select id="beisu">
            <option value="0.5">0.5x</option>
            <option value="1" selected>1.0x</option>
            <option value="1.25">1.25x</option>
            <option value="1.5">1.5x</option>
            <option value="2">2.0x</option>
        </select>
        
            $("#beisu").on("change", function(){
                var v = $(this).val();
                if (useVlc) {
                    VLC.input.rate = v;
                } else {
                    VIDEO.playbackRate = v;
                }
            });

8、快进、快退

        // 快进10秒播放
        function kuaijin() {
            if(useVlc){
                VLC.input.time += 10000;
            }else{
                VIDEO.currentTime += 10;
            }
        }

        // 快退10秒播放
        function kuaitui() {
            if(useVlc){
                VLC.input.time -= 10000;
            }else{
                VIDEO.currentTime -= 10;
            }
        }

四、完整代码+demo

github仓库地址:vlc-video

查看原文

子羽 回答了问题 · 2019-03-13

select触发change事件如何获取之前的值

之前的想法是绑定change事件的同时也绑定click事件,但是发现会先触发click,再触发change,最后再触发click。当然这样就没法达到我想要的效果,但是将click事件改为focus事件,就可以了

var prevValue = "";
$('select').on('focus',function(){
    prevValue = $(this).val();// 记录select之前选中的值
}).on('change',function(){
    if(canChange){
        // 可以更改
    }else{
       $(this).val(prevValue);// 将select值还原
    }
})

关注 3 回答 4

认证与成就

  • 获得 20 次点赞
  • 获得 31 枚徽章 获得 0 枚金徽章, 获得 9 枚银徽章, 获得 22 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • 悦读

    从后端服务、前端的APP、后台管理全都是我一人完成,一个阅读的系统——悦读

  • ltouch

    原生js编写的移动端手势滑动插件

注册于 2017-07-09
个人主页被 974 人浏览