2019年3月

前言

为什么要使用wsl来配置呢?因为我个人感觉这个比较方便,不用安装一堆包。直接敲命令就好。

准备工作

安装好Clion后,打开toolchain是这样的。
2019-03-28T01:51:00.png

前提是先装好wsl

选择wsl toolchain

会出现下面这个情况
2019-03-28T01:52:22.png
这是因为wsl没有配置ssh服务

配置wsl的ssh

sudo vi /etc/ssh/sshd_config

把密码认证的no改为yes

PasswordAuthentication yes

restart ssh

sudo service ssh restart 

如果出现以下提示
2019-03-28T02:15:33.png
则需要生成key

sudo dpkg-reconfigure openssh-server

查看ssh运行状态

service ssh status

configure remote credentials

2019-03-28T02:00:48.png
2019-03-28T02:16:37.png

配置编译环境

在wsl里面执行

sudo apt-get install build-essential gcc g++ cmake gdb

2019-03-28T05:16:09.png

安装pip3

sudo apt-get install python3-pip

安装Django

sudo pip3 install django

验证安装

2019-03-26T06:49:38.png

创建项目

django-admin startproject convert

运行

python3 manage.py runserver

2019-03-26T07:53:45.png

大致思路

  1. 注册表新建目录右键项
  2. 填写WSL命令行
如果你觉得添加起来过于麻烦,你可以双击执行下列注册表文件

wsl.reg

一些简介

注册表百科

注册表(Registry,繁体中文版Windows操作系统称之为登录档)是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息。早在Windows 3.0推出OLE技术的时候,注册表就已经出现。随后推出的Windows NT是第一个从系统级别广泛使用注册表的操作系统。但是,从Microsoft Windows 95操作系统开始,注册表才真正成为Windows用户经常接触的内容,并在其后的操作系统中继续沿用至今。

打开方式

  1. Win + R键入regedit

操作流程

  1. 目录导航输入HKEY_CLASSES_ROOT\Directory\shell
  2. 新建项ubuntu
  3. 选择ubuntu项,新建字符串值:名称为默认,值为WSL

如图:2019-03-25T02:28:02.png

  1. 在ubuntu项内添加command项
  2. 字符串名称为默认,值为wsl.exe --cd "%V"

如图:2019-03-25T02:30:30.png

截至目前,存在的问题

就是只有在选择一个目录时才会出现这个东西,右键空白处啥都不会发生

解决方法

HKEY_CLASSES_ROOT\Directory\Background\shell也同样操作一波

效果预览

我去,我不知道怎么截右键这个状态。

引言

我在很久之前就想研究这个项目,然后再进行些自定义的修改了。就以本文作为笔记开始吧。

项目目录树

.
├── Action.php
├── Plugin.php
├── Users.php
├── res //一些图片资源
│   ├── cvbg.jpeg
│   ├── cvborder.jpeg
│   ├── resend.png
│   └── test.bin
├── sql // 创建了两个数据库
│   ├── wetypecho.sql
│   └── wetypecholike.sql
└── tree.txt

查看数据库结构

wetypecho.sql
CREATE TABLE `typecho_wetypecho` (
  `id`                int(10) unsigned NOT NULL auto_increment,
  `openid`            varchar(255)     default ''  ,
  `createtime`        int(10)          default 0   ,
  `lastlogin`         int(10)          default 0   ,
  `nickname`          varchar(255)     default ''  ,
  `avatarUrl`         varchar(255)      default ''  ,
  `city`              varchar(255)      default ''  ,
  `country`           varchar(255)      default ''  ,
  `gender`            varchar(255)      default ''  ,
  `province`          varchar(255)     default ''  ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

看内容可以推测,这是微信用户数据表。

wetypecholike.sql
CREATE TABLE `typecho_wetypecholike` (
  `id`                int(10) unsigned NOT NULL auto_increment,
  `openid`            varchar(255)     default ''  ,
  `cid`               int(10)          default 0   ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这应该是个微信点赞表

php代码分析

激活进行的初始化操作代码

Helper::addRoute('jsonp', '/api/[type]', 'WeTypecho_Action');
        Helper::addAction('json', 'WeTypecho_Action');
        Helper::removePanel(1, 'WeTypecho/users.php');
        Helper::addPanel(1, 'WeTypecho/Users.php', 'WeTypecho', '我的用户', 'administrator');
        $db = Typecho_Db::get();
        $prefix = $db->getPrefix();
        Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('WeTypecho_Plugin','view_count');
        //创建用户数据库
        $scripts = file_get_contents('usr/plugins/WeTypecho/sql/wetypecho.sql');
        $scripts = str_replace('typecho_', $prefix, $scripts);
        $scripts = explode(';', $scripts);
        try {
            if (!$db->fetchRow($db->query("SHOW TABLES LIKE '{$prefix}wetypecho';", Typecho_Db::READ))) {
                foreach ($scripts as $script) {
                    $script = trim($script);
                    if ($script) {
                        $db->query($script, Typecho_Db::WRITE);
                    }
                }
            }
        } catch (Typecho_Db_Exception $e) {
            throw new Typecho_Plugin_Exception(_t('数据表建立失败,插件启用失败,错误信息:%s。', $e->getMessage()));
        } catch (Exception $e) {
            throw new Typecho_Plugin_Exception($e->getMessage());
        }
        //创建赞数据库
        $scriptslike = file_get_contents('usr/plugins/WeTypecho/sql/wetypecholike.sql');
        $scriptslike = str_replace('typecho_', $prefix, $scriptslike);
        $scriptslike = explode(';', $scriptslike);
        try {
            if (!$db->fetchRow($db->query("SHOW TABLES LIKE '{$prefix}wetypecholike';", Typecho_Db::READ))) {
                foreach ($scriptslike as $script) {
                    $script = trim($script);
                    if ($script) {
                        $db->query($script, Typecho_Db::WRITE);
                    }
                }
            }
        } catch (Typecho_Db_Exception $e) {
            throw new Typecho_Plugin_Exception(_t('数据表建立失败,插件启用失败,错误信息:%s。', $e->getMessage()));
        } catch (Exception $e) {
            throw new Typecho_Plugin_Exception($e->getMessage());
        }
        //创建赞数据库
        try {
            //增加点赞和阅读量
            if (!array_key_exists('views', $db->fetchRow($db->select()->from('table.contents'))))
            {
                $db->query(
                    'ALTER TABLE `' . $prefix
                    . 'contents` ADD `views` INT DEFAULT 0;'
                );
            }
            if (!array_key_exists('likes', $db->fetchRow($db->select()->from('table.contents'))))
            {
                $db->query(
                    'ALTER TABLE `' . $prefix
                    . 'contents` ADD `likes` INT DEFAULT 0;'
                );
            }
            if (!array_key_exists('authorImg', $db->fetchRow($db->select()->from('table.comments'))))
            {
                $db->query(
                    'ALTER TABLE `' . $prefix
                    . 'comments` ADD `authorImg` varchar(500) DEFAULT NULL;'
                );
            }
        } catch (Exception $e) {
            echo($e->getMessage());
        }

js类似于printf那样的格式化字符串

安装包
npm install sprintf-js
调用包
var sprintf = require('sprintf-js').sprintf,
操作实例:时间前补零操作
for (let i = 46; i >= 0; i--) {
        console.log(sprintf('%2d:%02d', i / 2, (i % 2 ? 0 : 30)))
      }

引言

首先看一张最终效果图

终端.PNG

大致思路

使用win10的linux子系统,安装zsh,默认切换zsh终端。(什么鬼,这和装虚拟机有什么不一样?放心,不一样的,慢慢看)

为什么要需要它?

  1. cmd太丑,cmder略慢,然后就是命令的不统一性。
  2. 一个好看的终端可以让程序员变得开心又愉快。
如下

截图.PNG

准备工作

  1. win10内部版本16215.0以上
  2. 打开win10开发人员模式
  3. 勾选控制面板>程序>启用windows功能>linux子系统
  4. 重启
  5. 打开应用商店>搜索linux, 选择你喜欢的linux发行版安装,我选的是ubuntu18.04,如果卸载了应用商店可以自行百度开启方式

-- 至此:linux系统安装成功

在linux子系统中需要做的操作

在开始栏运行ubuntu

或者win+R,键入wsl运行。

安装zsh

sudo apt-get install zsh

设置默认shell

chsh -s /bin/zsh

安装oh-my-zsh

sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"

(可选项)修改主题

nano ~/.zshrc
我的修改如下

2019-03-12T07:02:46.png

让bash每次打开自动执行zsh

重新打开终端窗口,我们目前的效果是这样的。

ssh1.PNG

然后就会发现,这丫的,这怎么跟我的win10保持文件共享呢?

让linux子系统默认打开win10用户根目录

  1. 首先找到C\\windows\\system32\\wsl.exe,复制到你的win10用户根目录。
  2. 再为根目录的bash.exe创建快捷方式发送到桌面。
  3. 运行
看,好神奇

2019-03-12T07:14:16.png

可是,,,难道每次我运行命令都要回到桌面启动?而且就不能像ubuntu那样ctrl + alt + T打开?

为适应win10的一些配置

  1. 右键点击桌面快捷方式,选择快捷键,同时按ctrl + alt + T设置快捷键。
  2. 桌面右键>选择查看>取消勾选显示桌面图标
测试ctrl + alt + T,我可能是为数不多的秀win10桌面的程序员:) (好像还是没有linux的好看?)

2019-03-12T07:23:44.png

在vs code里配置默认终端为wsl.exe。效果展示

2019-03-12T07:27:41.png

结束语

因为截图会变模糊,实际效果比这好看的多,嗯,又多了一个装逼的东西。

为啥需要这个?

有时候我们写微信小程序,写好了。在手机上运行感觉效果还不错,正想分享给别人。突然发现没有分享选项,纳尼?原来是忘记写onShareAppMessage()了。有得加上,再编译。不得不说,麻烦的一匹。

应运而生

然后我就想,要是可以让默认支持分享就好了。

wepy实现方法

大致思路

import wepy from 'wepy';
export default class Page extends wepy.page {
}
分析代码,发现所有的page都继承于wepy.page, 而wepy.page又继承于wepy.component. 这感情好。也就意味着我只需要构建一个超类继承wepy.page就可以了

实践

新建page.js文件,内容如下
import wepy from 'wepy';
export default class Page extends wepy.page {
    onShareAppMessage() {
        
    }
}
然后再调整一下页面继承
import Page from '../page';
export default class Index extends Page {
}
编译运行,果然如此!

如果要自定义分享内容怎么办?

在子page里面重构onShareAppMessage就可以啦。

tips: 现使用uni-app后发现已经默认支持分享了

后续: uni-app说这是个BUG,已经修复了。。

后备方案——使用mixin全局混入

  1. 在main.js中添加以下内容。
import qs from 'query-string'
Vue.mixin({
    onShareAppMessage() {
        console.log('分享路径', '/pages/index?route=' + this.$mp.page.route + '&' + qs.stringify(this.$mp.query))
        return {
            path: '/pages/index?route=' + this.$mp.page.route + '&' + qs.stringify(this.$mp.query)
        };
    }
})

以上代码实现了所有页面都支持转发,并将转发路径设为主页。

  1. 在主页的onLoad函数中加入以下内容
if (options.route) {
                uni.navigateTo({
                    url: '/' + options.route + '?' + qs.stringify(options)
                })
            }

这样就实现了,进入后的页面跳转。

  1. 为什么要这样做?

因为大家都知道,当我们直接分享小程序页面给别人的时候。别人点击进入非tab页面,是没有返回操作的。增加了上面的功能后,所有页面的分享,都会先进入主页,再跳转至分享的页面。用户就可以无缝对接啦!

更新,现小程序已支持页面返回

想达到本文效果,需使用wepy框架。不了解wepy?转https://tencent.github.io/wepy/index.html

什么是async/await?

在最新的ES7(ES2017)中提出的前端异步特性:async、await。
async顾名思义是“异步”的意思,async用于声明一个函数是异步的。而await从字面意思上是“等待”的意思,就是用于等待异步完成。也就是我们平常所说的异步等待。不过需注意await只能在async函数中使用

为什么需要async/await?

在async/await之前,我们有三种方式写异步代码

1. 嵌套回调

其中思想就是,a函数执行完了得到的结果后在执行b。
形如

wx.getSetting({
      success(res) {
        console.log(res.authSetting['scope.userLocation']);
        if (!res.authSetting['scope.userLocation']) {
          wx.authorize({
            scope: 'scope.userLocation',
            fail(res) {
              Toast('无法获取位置,采用默认排序');
            }
          });
        } else {
          wx.getLocation({
            type: 'wgs84',
            success(res) {
              _this.setData({ location: res });
              console.log('您的位置信息:', res);
            },
            fail() {
              Toast('无法获取位置,采用默认排序');
            }
          });
        }
      }
    });
上面的代码你不用看,就会感觉。这啥东西?乱七八糟的。这就是嵌套回调。很不巧,原生微信小程序开发就是这样的。

2. 以Promise为主的链式回调

所谓Promise,简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。形如
var p1 = new Promise((resolve, reject) => {
 setTimeout(resolve, 1000, 'done');
 })
p1.then(data=>{
 console.log(data); // done
})

如果你的函数够多的话,那么就会一直then()下去。

为了优雅,Promise提供了一个方法Promise.all([p1,p2,p3]) ,用于将多个Promise实例,包装成一个新的Promise实例。接收的参数是一个数组,p1、p2、p3都是Promise对象
分两种情况:
  1. p1、p2、p3的状态都是resolve的时候,Promise.all的状态才会变成resolve;
  2. 只要p1、p2、p3中有一个的状态为reject,那么Promise.all的状态就会变成reject;

所以我们可以用Promise.all()来解决多个异步依赖调用。

3. 使用Generators

function *main() {
    var x = yield 1;
    var y = yield x;
    var z = yield (y * 2);
}
上面代码中的每一条语句都会按顺序一个一个地执行。Yield关键字标明了代码中被阻塞的点(只能被generator函数自己阻塞,外部代码不能阻塞generator函数的执行),但是不会改变*main()函数中代码的执行顺序。这段代码很简单!

但是,这三种写起来都还是不够优雅,ES7做了优化改进,async/await应运而生,async/await相比较Promise 对象then 函数的嵌套,与 Generator 执行的繁琐(需要借助co才能自动执行,否则得手动调用next()), Async/Await 可以让你轻松写出同步风格的代码同时又拥有异步机制,更加简洁,逻辑更加清晰。

示例
async a(){};
const b = await a();

这样做的好处?

唔,你不觉得一个优雅的代码就该是这样吗?好吧,其实这样更容易符合我们平常的思维逻辑

回到本文的题目

在wepy1.4.1以后的版本(之前的版本都是默认开启的),默认不支持async/await,需要用户手动加入,方法如下:

进入项目根目录,安装runtime包

npm install wepy-async-function --save

修改wepy.config.js加入runtime配置

        babel: {
            "presets": [
                "env"
            ],
            "plugins": [
                "transform-export-extensions",
                "syntax-export-extensions"
            ]
        }

在app.wpy中引入引入runtime包

import 'wepy-async-function'; 

在app.wpy中使API promise化

重写构造函数,使其支持async/await。
export default class extends wepy.app {
    constructor () {
        super();
        this.use('promisify');
    }
}

重启编译

wepy build --no-cache

使用示例

在wepy框架官方文档中已说明,对所有的微信小程序都支持async/await操作。只需将形如wx.getuserInfo改写为wepy.getuserInfo即可
async userInfoAsync() {
    const _this = this;
    const data = await wepy.getSetting(); //获取设置数据
    if (data.authSetting['scope.userInfo']) { //判断是否有获取用户信息的权限
      await wepy.login(); //登录
      let data = await wepy.getUserInfo();//获取用户信息
      _this.userInfo = data.userInfo;//采用wepy框架修改过后的功能,支持直接赋值数据绑定
      _this.$apply(); //在async的函数中,必须主动执行`$apply()`来进行脏数据检查
    }
  }
async onShow() {
    this.userInfoAsync(); //调用async函数
  }
以上代码实现了异步同步用户userInfo的功能

参考文献:

  1. 使用Promise链式调用解决多个异步回调的问题
  2. 关于js的callback回调函数以及嵌套回调函数的执行过程理解
  3. ES6 Generators并发
  4. ES7前端异步玩法:async/await理解
  5. 理解 JavaScript 的 async/await
  6. Async/await学习
  7. 浅谈async/await
  8. wepy项目中使用async await