在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。 – 维基百科

函数柯里化的好处在于:

  • 函数复用,提高适用性
  • 延迟执行

1.函数复用:

const match = (reg, str) => {
  console.log(str.match(reg));
};

const reg = /\s+/g;
// 重复调用reg变量
match(reg, 'hello world'); // [" "]
match(reg, 'spaceless'); // null

函数柯里化实现:

const curry = fn => {
  return (...args) => {
    return (...cb) => {
	  // 合并参数,立即执行
      return fn.apply(null, [...args, ...cb]);
    };
  };
};

const match = curry((reg, str) => {
  console.log(str.match(reg));
});
const hasSpace = match(/\s+/g);

hasSpace('hello world'); // [" "]
hasSpace('spaceless'); // null

缩小函数的适用范围,但同时提高函数的适用性

2.延迟执行

const curry = (fn) => {
  return (...args) => {
    return function _f() {
      if (arguments.length) {
        // 参数不为空,合并参数
        args.push(...arguments);
        // 返回自身,链式调用
        return _f;
      }
      // 参数为空,立即执行
      return fn.apply(null, args);
    };
  };
};

// 累加方法
const add = curry((...arr) => {
  return arr.reduce((next, p) => {
    return next + p;
  }, 0);
});

console.log(add(1, 2, 3, 4)(5)()); // 15
console.log(add(1)(2)(3)(4)(5)()); // 15

累积传入参数,当不传参数的时候,最后执行。

参考地址:

阅读全文

flex-growflex-shrinkflex-basis这三个属性的作用是:在flex布局中,父元素在不同宽度下,子元素是如何分配父元素的空间的。

flex-basis

该属性来设置该元素的宽度。 当然,width也可以用来设置元素宽度。如果元素上同时设置了width和flex-basis,那么flex-basis会覆盖width的值。他的默认值为auto

flex-grow

该属性来设置,当父元素的宽度大于所有子元素的宽度的和时(即父元素会有剩余空间),子元素如何分配父元素的剩余空间。默认值为0

示例代码: http://runjs.cn/code/mwprzdop

flex-shrink

该属性来设置,当父元素的宽度小于所有子元素的宽度的和时(即子元素会超出父元素),子元素如何缩小自己的宽度的。默认值为1

示例代码: http://runjs.cn/code/54jqeffn

总结

如果父级的空间足够:flex-grow有效,flex-shrink无效。

如果父级的空间不够:flex-shrink 有效,flex-grow无效。

阅读全文

Vue构建的大多是SPA单页面应用,但有时候在实际项目中单页面应用并不一定符合业务需求

准备工作

利用vue-cli新建项目,再执行npm install命令安装所需依赖,之后需安装新依赖glob

npm install --save-dev glob

修改webpack配置

需要改动的文件都在build文件夹下:

  • util.js
  • webpack.base.conf.js
  • webpack.dev.conf.js
  • webpack.prod.conf.js

utils.js 文件

// glob是webpack安装时依赖的一个第三方模块,还模块允许你使用 *等符号
// 例如lib/*.js就是获取lib文件夹下的所有js后缀名的文件
const glob = require('glob');
// 页面模版文件路径
const page_path = path.join(__dirname, '../src/module');
// 页面模板插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 融合相应的配置
const merge = require('webpack-merge');

// 多页面入口文件配置
// 通过glob模块读取pages文件夹下的所有对应文件夹下的js后缀文件,如果该文件存在
// 那么就作为入口文件之一
exports.entry = _ => {
  var entryFiles = glob.sync(page_path + '/*/*.js');
  var map = {};
  entryFiles.map(filePath => {
      let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'));
      map[filename] = filePath;
  });
  return map;
}

// 多页面输出配置
// 与上面的多页面入口文件配置相同,读取pages文件夹下的对应的html后缀文件,然后放入数组中
exports.HtmlWebpackPlugin = _ => {
  var entryFiles = glob.sync(page_path + '/*/*.html');
  var arr = [];
  entryFiles.map(filePath => {
      let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'));
      let config = {
          // 模板来源
          template: filePath,
          // 文件名称
          filename: filename + '.html',
          inject: true,
          // 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
          chunks: ['manifest', 'vendor', filename]
      }
      // 生产环境加入新配置,该配置是原webpack.prod.conf.js中相对于webpack.dev.conf.js新增配置
      if (process.env.NODE_ENV === 'production') {
          config = merge(config, {
              minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeAttributeQuotes: true
              },
              chunksSortMode: 'dependency'
          })
      }
      arr.push(new HtmlWebpackPlugin(config));
  });
  return arr;
}

webpack.base.conf.js 文件

原:

entry: {
    app: './src/main.js'
},

替换成

entry: utils.entry(),

webpack.dev.conf.js 文件

注释掉:

plugins: [
    // new HtmlWebpackPlugin({
    //     filename: 'index.html',
    //     template: 'index.html',
    //     inject: true
    // }),
]

并在

plugins: [].concat(utils.HtmlWebpackPlugin())

webpack.prod.conf.js 文件

同上注释掉:

plugins: [
    // new HtmlWebpackPlugin({
    //     filename: config.build.index,
    //     template: 'index.html',
    //     inject: true,
    //     minify: {
    //         removeComments: true,
    //         collapseWhitespace: true,
    //         removeAttributeQuotes: true
    //             // more options:
    //             // https://github.com/kangax/html-minifier#options-quick-reference
    //     },
    //     // necessary to consistently work with multiple chunks via CommonsChunkPlugin
    //     chunksSortMode: 'dependency'
    // }),
]

并在

plugins: [].concat(utils.HtmlWebpackPlugin())

至此,webpack的配置就结束了。

文件结构

.
├── README.md
├── build
│   ├── build.js
│   ├── check-versions.js
│   ├── logo.png
│   ├── utils.js
│   ├── vue-loader.conf.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config
│   ├── dev.env.js
│   ├── index.js
│   └── prod.env.js
├── package.json
├── src
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   ├── Hello.vue
│   │   └── cell.vue
│   └── module
│       ├── cell
│       │   ├── cell.html
│       │   ├── cell.js
│       │   └── cell.vue
│       └── index
│           ├── index.html
│           ├── index.js
│           ├── index.vue
│           └── router
│               └── index.js
└── static

src为默认工程文件,其中的assets,components,module分别是静态资源文件、组件文件、页面文件。 页面文件中按照项目的模块分的文件夹,每个文件夹下分别有三个内容:vue文件,js文件和html文件。这三个文件的作用就相当于做spa单页面应用时,根目录的index.html页面模板,src文件下的main.jsapp.vue的功能。

现在可以直接运行npm start试试看效果

相关代码:

参考地址:

阅读全文

公司之前版本控制工具一直用的是SVN,自己的代码放在github,结果新项目需要用到公司搭建的gitlab,生成的sshkey覆盖了原本我github的秘钥,之前还没发现,一次在github查看push日志突然发现提交人不对了: 后来在网上找到解决办法:

1. 进行公司账号的设置:

ssh-keygen -t rsa -C "注册的gitlab邮箱",就用默认密钥名称,密码的话直接跳过吧,然后在~/.ssh能找到id_rsaid_rsa.pub 把id_rsa.pub的内容添加到到gitlab账户的的SSH Keys中即可

2. 生成github秘钥:

终端执行命令:ssh-keygen -t rsa -C "注册的github邮箱",这次一定要注意,对生成定的秘钥进行重命名,我这里命名的是id_rsa_github,同样不设置密码。可以看到生成的公私秘钥已经分别被重命名为id_rsa_github.pubid_rsa_github

将id_rsa_github.pub的内容拷到github的SSH Keys里

3. 配置config:

终端运行:touch config,输入:

Host gitlab
HostName 192.168.13.21
IdentityFile ~/.ssh/id_rsa
Host github
HostName github.com
IdentityFile ~/.ssh/id_rsa_github

其中Host对应的名称是一个别名,命名可以随意,用来进行远程连接,当然使用真实的主机名称也是可以的。HostName和IdentityFile就是各自主机名称以及对应的秘钥文件了~ 这样配置之后,两份秘钥也就对应到各自相应的仓库上了。通过设置别名,也就可以设置任意多的账户了~

4. 最后利用别名检测下配置是否成功:

4.1 检测github连接:

4.2 检测gitlab连接:

不报错的话,就说明设置成功了!

参考地址:

阅读全文

后台一直都是密码登录,简直枯燥的没朋友,看见小伙伴的博客设置的是扫描二维码登录,然后请教了一番加上自己的理解,实现了小程序配合扫码登录后台

首先是要理解扫码登录的逻辑,在我看来扫码的小程序就是superadmin,扫码就能实现后台的token生成,保存到redis,发放给前端页面,所以小程序的权限设置是很重要的,这里单独新增一个表:tp_wx,存放微信账号的唯一标识,可读可写:

OPEN_ID字段就是小程序里 wx.login 方法的返回值,用户唯一标识, 数据库里不存在该OPEN_ID的话当然是没有权限的:

下面是简单的思路:

  1. websocket连接服务端之后保存一个自定义的标识,对应相应客户端,下面把这个标识称之为key

  2. 再把这个key通过qrcode生成二维码显示到页面上等待小程序扫码读取

  3. 小程序扫码后,获取到这个key并发送给服务端

  4. 服务端再通过小程序发送的key找到对应的客户端并提示登录成功或者失败

具体代码已上传至github: websocket-wxApp-login

参考地址:

阅读全文