VSCode 开发相关知识

vscode 项目简介

参考wiki: link

运行vscode

1
2
./scripts/code.sh
./scripts/code-cli.sh # for running CLI commands (eg --version)

打包vscode

1
yarn gulp vscode-win32-x64

vscode 插件开发

左边的view只能设置id和name Link, 具体高度应该需要WebviewView或者TreeView去撑

activationEvents

  • onLanguage:${language}
  • onCommand:${command}
  • onDebug
  • workspaceContains:${toplevelfilename}
  • onFileSystem:${scheme}
  • onView:${viewId}
  • onUri
  • *

跳转定义

vscode.languages.registerDefinitionProvider

自动补全

vscode.languages.registerCompletionItemProvider–

高阶函数

高阶函数介绍

用于过程抽象,提取相同逻辑便于复用。概念与函数的装饰器类似。

概念

高阶函数,即返回一个函数的函数。它可以在原基础上对函数做出若干改进,增加一些新的功能或者增强。

Once函数

Once函数使传入的函数只会运行一次,用于单例模式初始化,删除元素后阻止响应。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Only allow the function run once
* @param {[Function]} fun The function need to be changed
*/
function once(fun) {
return function(...args) {
if (fun) {
const ret = fun.apply(this, args);
fun = null;
return ret;
}
}
}

throttle函数

throttle函数,即节流函数。在特定时间里只运行一次,丢弃之后的执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Only run once in the specified time range.
* @param {[Function]} fun The function need to be changed
* @param {[Number]} ms The time need to be throttle
*/
function throttle(fun, ms) {
let throttleTimer = null;
return function(...args) {
if (!throttleTimer) {
throttleTimer = setTimeout(function() {
const ret = fun.apply(this, args);
throttleTimer = null;
return ret;
}, ms)
}
}
}

debounce函数

防抖函数,在特定时间段内取消重复的运行,只会运行最后一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Only run the last time in the specified time range.
* @param {[Function]} fun The function need to be changed
* @param {[Number]} ms The time need to be debounced
*/
function debounce(fun, ms) {
let debounceTimer = null;
return function(...args) {
if (debounceTimer) {
clearTimeout(debounceTimer);
}
debounceTimer = setTimeout(function() {
const ret = fun.apply(this, args);
return ret;
}, ms)
}
}

wait函数(工具函数)

setTimeout函数的Promise版重新组织方式

1
2
3
4
5
6
7
8
9
/**
*
* @param {number} duration The time need to waiting.
*/
function wait(duration) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
})
}

retry函数

返回一个Promise,会重试n次后再返回失败

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
*
* @param {Promise} promise The Promise need to be wrapped
* @param {number} times The times should be retried
*/
function retry(promise, times) {
return new Promise((resolve, reject) => {
function loop() {
const tempPromise = Promise.resolve(promise)
tempPromise.then(res => {
resolve(res)
}).catch(e => {
if (times--) {
console.log('failing')
loop()
} else {
reject(e)
}
})
}
loop();
})
}

Witcher

巫师三 狂猎 游戏记录

装备

毒蛇银剑 绿宝石之尘获取方式
毒蛇钢剑

猎魔人套装

  1. 狮鹫学派套装
  2. 猫学派套装
  3. 狼学派套装
  4. 熊学派套装

游戏记录

目前正在玩的游戏

1. 星际争霸
2. 对马岛之魂
3. 只狼
4. 战神
5. 死亡搁浅
6. 糖豆人
7. 帝国时代(玩玩战役,打打自定义)
8. 上古卷轴(正在玩)
9. 巫师(正在玩)
10. 动物之森(正在玩)
11. 生化危机2(里昂篇)

### 期待的游戏
1. 赛博朋克2077(等发布)

心情疏导

年轻,为什么不拼搏?
别人行,有什么借口不行?
别人在努力,为什么可以不努力?
活在当下,拒绝拖延。
真正的自由是灵魂的自由,想到就去做,这才是青春。
无奋斗,不青春………^_^

将近四年后再进行一次更新,自己最近事很多,尽量让自己不焦虑,不抑郁。过了这段就好了,强度无非就是之前北京那样了。
焦虑主要是因为自己开发时需求不明晰,加上赶进度自测也不到位,完成度不高。结果导致后期bug数较多。这也没办法,需求和进度自己也不太好掌握。后期尽量提高完成度,修改出一个可用的版本。
现在bug改完了,心态也调整了好多。发现现在自己身边好多都有心理问题,看来疏通引导是很重要的事情

最近因为疫情闲了很长时间,也抽时间做了些自己的东西。挺好的。

再一次进行更新,现在项目准备发布。但每次发布前都会有新需求改动和细节Bug,没有截版。不知道正式发布会到什么时候。

VScode常用配置以及使用技巧

1. 代码片段


代码片段。即一些提前定义的可重复使用的小代码段,使用此功能可以比较方便地以简单的操作输入一些重复而又没有办法避免的代码段。
例如创建api, action, vue文件时,我们使用一些通用的模板,这时可以使用定义好的代码片段,不仅避免了重复拷贝操作,更从工具层面统一了这些文件的编写规范,提升团队效率。
使用:文件 -> 首选项 -> 用户代码片段 -> 新增代码片段
生成代码片段后进行代码片段文件编写,生成文件中有默认实例
snippets文件示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    // 添加Api主文件
    "Create an api file": {
        "scope": "javascript,typescript", // 可使用的文件类型
        "prefix": "create-api", // 调用时的命令
        "body": [
            "export const $1 = (params) => {",
            " return http.$2('$3', params)",
"}",
// 生成的代码内容,$1, $2 ...分别表示按tab键后的定位位置,方便快速输入
        ],
        "description": "initialize an action js file" // 代码片段描述
    }
}

使用时在相应文件输入设定好的prefix值,即会出现相应的命令
可配置项目相关的代码片段,放在项目中的 .vscode 文件夹中

2. 初次安装vscode时同步配置


安装sync-setting插件。此插件可以把vscode的设置,包括安装哪些插件,键位绑定,用户代码片段等上传到github上予以托管。当新的电脑需要这些配置的时候可以很方便地进行下载,实现了vscode的设置同步功能。
使用方法:具体文档
上传:输入sync-setting选择上传设置选项
访问 https://github.com/settings/tokens 创建token并记录,输入进行上传
下载:输入sync-setting选择下载设置选项
输入token以及Gist ID 进行设置下载,数据新员工可向老员工询问

3. 前端开发常用技巧以及工具


CSScomb (CSS代码规范与整理插件)

CSScomb可以很方便地对css代码进行美化功能,支持属性顺序配置。可以很方便地避免因css代码不规范造成的问题。示例配置文件
使用说明:

  1. 在vscode应用中搜索csscomb并进行下载
  2. 进行代码风格配置: 点击后选择相应的代码格式,生成配置文件 生成代码风格配置
  3. 进行css属性顺序配置:配置示例
  4. 将配置好的文件写入setting.json文件中
    postman(测试后端接口,发送请求)
    postman经常用来发送特定请求来测试后台返回数据是否正常,在谷歌商店中安装并进行使用,也可下载本地端。官网下载:https://www.getpostman.com/products
    FeHelper(前端常用工具合集)
    此工具为百度团队开发的一款前端工具集,包含了一些前端开发中比较常用的工具。例如json格式化,编解码,正则测试等功能。
    github: https://github.com/zxlie/FeHelper
    webpack-bundle-analyzer (打包分析工具,分析包依赖以及占用的大小)
    插件需在代码中进行配置,配置完成后在build完成后会打开网页展现各种依赖包的大小关系以及依赖关系,供分析依赖提升工程性能使用。
    npm: https://www.npmjs.com/package/webpack-bundle-analyzer
    iconfont(矢量图标库,可让UI负责图标库管理)
    官方网站:https://www.iconfont.cn/
    webpack alias配置
    此方法可以通过比较简单的路径访问到资源,防止多层 ../ 的出现以及嵌套过深的情况
    例如:
    import HelloWorld from '../../../../../HelloWrold.vue'
    此情况下,我们可以配置package.json文件中的alias来解决问题。在vue-cli 3.0中,我们配置chainWebpack进行间接修改
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /* vue.config.js */
    module.exports = {
    ...
    chainWebpack: config => {
    config.resolve.alias
    .set('@', resolve('src'))
    .set('_lib', resolve('src/common'))
    .set('_com', resolve('src/components'))
    .set('_img', resolve('src/images'))
    .set('_ser', resolve('src/services'))
    },
    ...
    }
    这样,我们的例子可以改写为
    import HelloWorld from '_com/HelloWorld.vue'

    注意:在样式或者模板中引用路径时需在前加上~符号,否则路径解析会失败

Chrome V8 系统管道简介

V8 简介

相信很多的朋友都听过前端界的一个著名定律,叫做 Atwood’s Law。2007 年,Jeff Atwood 提出 “所有可以用 JavaScript 编写的应用程序最终都会用 JavaScript 编写”。转眼 12 年过去,现在,我们的确可以看到,JavaScript 在浏览器端、服务端、桌面端、移动端、IoT 领域都发挥着作用。
另一方面,截至目前(2019-11-08),Chrome 在全平台的市场占有率已经达到 64.92%(数据来源:StatCounter)。作为 Chrome 的 JavaScript 引擎,V8 在 Chrome 扩大市场占有率方面也起到十分关键的作用。
作为最强大的 JavaScript 引擎之一,V8 同样是无处不在。在浏览器端,它支撑着 Chrome 以及众多 Chromium 内核的浏览器运行。在服务端,它是 Node.js 及 Deno 框架的执行环境。在桌面端和 IoT 领域,也同样有 V8 的一席之地。
V8 是使用 C++ 编写的高性能 JavaScriptWebAssembly 引擎,支持包括我们熟悉的 ia32、x64、arm 在内的八种处理器架构。
V8 的重要部件
Ignition(基线编译器)
TurboFan(优化编译器)
Orinoco(垃圾回收器)
Liftoff(WebAssembly 基线编译器)

V8管道简介

早期 V8 执行管道由基线编译器 Full-Codegen 与优化编译器 CrankShaft 组成。

image1
其中,基线编译器更注重编译速度,而优化编译器更注重编译后代码的执行速度。综合使用基线编译器和优化编译器,使 JavaScript 代码拥有更快的冷启动速度,在优化后拥有更快的执行速度。

这个架构存在诸多问题,例如,Crankshaft 只能优化 JavaScript 的一个子集;编译管道中层与层之间缺乏隔离,在某些情况下甚至需要同时为多个处理器架构编写汇编代码等等。
为了解决架构混乱和扩展困难的问题,经过多年演进,V8 目前形成了由解析器、基线编译器 Ignition 和优化编译器 TurboFan 组成的 JavaScript 执行管道。

image2

在执行管道改进的过程中,通过引入 IR(Intermediate representation,中间表示),有效地提升了系统可扩展性,降低了关联模块的耦合度及系统的复杂度。

image3
image4

解析器与AST

解析代码需要时间,所以 JavaScript 引擎会尽可能避免完全解析源代码文件。另一方面,在一次用户访问中,页面中会有很多代码不会被执行到,比如,通过用户交互行为触发的动作。
正因为如此,所有主流浏览器都实现了惰性解析(Lazy Parsing)。解析器不必为每个函数生成 AST(Abstract Syntax tree,抽象语法树),而是可以决定“预解析”(Pre-parsing)或“完全解析”它所遇到的函数。

预解析会检查源代码的语法并抛出语法错误,但不会解析函数中变量的作用域或生成 AST。完全解析则将分析函数体并生成源代码对应的 AST 数据结构。相比正常解析,预解析的速度快了 2 倍。

生成 AST 主要经过两个阶段:分词和语义分析。AST旨在通过一种结构化的树形数据结构来描述源代码的具体语法组成,常用于语法检查(静态代码分析)、代码混淆、代码优化等。

生成AST可以通过在线工具AST Explorer进行体验。

基线编译器Ignition与字节码

V8 引入 JIT(Just In Time,即时编译)技术,通过 Ignition 基线编译器快速生成字节码进行执行。
字节码是机器码的抽象。如果字节码的设计与物理 CPU 的计算模型相同,那么将字节码编译成机器代码就会更加容易。

和之前的基线编译器 Full-Codegen 相比,Ignition 生成的是体积更小的字节码(Full-Codegen 生成的是机器码)。字节码可以直接被优化编译器 TurboFan 用于生成图(TurboFan 对代码的优化基于图),避免优化编译器在优化代码时需要对 JavaScript 源代码重新进行解析。

优化编译器 Turbo 优化与去优化

编译器需要考虑的函数输入类型变化越少,生成的代码就越小、越快。
众所周知,JavaScript 是弱类型语言。ECMAScript 标准中有大量的多义性和类型判断,因此通过基线编译器生成的代码执行效率低下。
举个例子,+ 运算符的一个操作数就可能是整数、浮点数、字符串、布尔值以及其它的引用类型,更别提它们之间的各种组合(ECMA对于+的定义)。

但这并不意味着 JavaScript 代码没有办法被优化。对于特定的程序逻辑,其接收的参数往往是类型固定的。正因为如此,V8 引入了类型反馈技术。在进行运算的时候,V8 使用类型反馈对所有参数进行动态检查。
简单来说,对于重复执行的代码,如果多次执行都传入类型相同的参数,那么 V8 会假设之后每一次执行的参数类型也是相同的,并对代码进行优化。优化后的代码中会保留基本的类型检查。如果之后的每次执行参数类型未改变,V8 将一直执行优化过的代码。而当之后某一次执行时传入的参数类型发生变化时,V8 将会“撤销”之前的优化操作,这一步称为“去优化”(Deoptimization)。

代码缓存

在用户访问相同的页面,并且该页面关联的脚本文件没有任何改动的情况下,代码缓存技术会让 JavaScript 的加载和执行变得更快。

代码缓存被分为 cold、warm、hot 三个等级。

用户首次请求 JS 文件时(即 cold run),Chrome 将下载该文件并将其提供给 V8 进行编译,并将该文件缓存到磁盘中。

当用户第二次请求这个 JS 文件时(即 warm run),Chrome 将从浏览器缓存中获取该文件,并将其再次交给 V8 进行编译。在 warm run 阶段编译完成后,编译的代码会被反序列化,作为元数据附加到缓存的脚本文件中。

当用户第三次请求这个 JS 文件时(即 hot run),Chrome 从缓存中获取文件和元数据,并将两者交给 V8。V8 将跳过编译阶段,直接反序列化元数据。

接口管理与Mock

1. 接口管理

在前后端分离开发的过程中,数据接口是程序中前后端的一个主要交互流转过程,接口管理的工程化程度直接影响了前后端联合开发的质量以及之后联调的效率。
为了业务项目开发的进一步前后端切分以及增加联调环节的效率,避免一些不必要的沟通协作问题。现在列出一些接口管理的约定建议。

  1. 接口统一生成文档在统一平台管理。
  2. 需在开发前商定好接口参数以及文档,前后端严格按照文档进行接口实现
  3. 文档应给出一组或者多组示例数据,供前端mock使用,避免后端接口进度影响
  4. 接口变动时应同步提醒相关的前后端开发人员,保持信息的时效性

对于前端的接口使用方面

  1. 严格按照文档进行接口mock,保证请求方式及参数正确
  2. 切记在前后端联调时删除业务文件中的mock部分
  3. 可编写对于接口的测试脚本,使用自动化工具以及测试用例进行一键测试,帮助减少后端接口问题
  4. 测试联调时出现问题应与文档对照,确保与文档一致无误后再与后端沟通接口异常问题

参考:阿里云API网关功能,可参考其功能逐渐完善api相关功能

2.数据Mock部分

前端工程中可使用Mock.js进行后端接口mock,这样可以使前端可以独立于后端开发单独进行开发,提高了开发效率。
使用Mock.js可以在不修改既有代码的情况进行Ajax请求拦截,返回预定好的数据。同时使用方法符合与平常接口调用,返回数据可使用内置函数进行随机数据模拟,更接近于真实数据,方便单元测试。
使用方法:

  1. 安装Mock.js
    npm install mockjs --save
  2. 在业务组件需要Mock的文件中进行调用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    /** mock begin */
    import Mock from 'mockjs'
    const Random = Mock.Random
    Mock.mock(/\/api\/demo/, 'post', options => {
    return {
    'content': {
    'data': {
    'name': Random.cname(),
    'id': Random.id(),
    'isTeacher': Random.boolean(),
    'create-time': Random.date('yyyy-MM-dd'),
    'color': Random.color(),
    'desc': Random.csentence(),
    'blog': Random.url('http', 'xshcs.com'),
    'hometown': Random.county(true),
    'classId': JSON.parse(options.body).lessonCode
    }
    },
    'code': 0,
    'msg': ''
    }
    })
    /** mock end */
  3. 根据业务需求更改mock正则匹配表达式,请求方式以及返回数据(模拟数据数据见官网示例)
  4. 前后端进行联调时删去mock注释中的内容即可

相应代码生成已经整合进code-snippets中(输入create-mock直接调用)

常用代码整理

javascript常用代码

字符串相关

1
2
3
substr(start, length) // 截取start开始长度为length的字符串
slice(start, end) // 返回start到end的子串,不改变原字符串
splice(start, deleteCount, item...) // 改变原来子串,从start位置开始,删除deleteCount个元素,插入item元素。后两个参数可选

判断数组中是否有该元素(可传比较函数)

1
2
3
4
5
6
7
8
9
/**
* find item in array
* @param {[type]} array [description]
* @param {[type]} item [description]
* @return {[boolean]} is the item in array
*/
function find(array, item) {
return !!~array.findIndex(element => (element === item));
}

日期格式化相关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function formatTime(date) {
var now = date || new Date();
var result = "";
result = now.getFullYear() + "年";
result += ("0" + (now.getMonth() + 1)).slice(-2) + "月";
result += ("0" + now.getDate()).slice(-2) + "日 ";
result += ("0" + now.getHours()).slice(-2) + ":";
result += ("0" + now.getMinutes()).slice(-2) + ":";
result += ("0" + now.getSeconds()).slice(-2) + " 星期";
result += transformZhCn(now.getDay());
return result;
}

function transformZhCn(index) {
let dataObj = {
0: '日',
1: '一',
2: '二',
3: '三',
4: '四',
5: '五',
6: '六'
};
return dataObj[index];
}

编码解码相关

1
2
3
4
5
6
JSON.parse(text, reviver); // 将text字符串转换为JSON对象,对每个对象成员调用reviver
JSON.stringify(value, replacer, space); //将value转换为字符串,每个对象键值调用replacer,插入space数量的空格
encodeURI(URIstring); // 编码url
encodeURIComponent(URIstring); // 以组件形式编码url
decodeURI(URIstring); // 解码url
decodeURIComponent(URIstring); // 以组件形式解码url

实用方法

1
2
3
[...Array(3).keys()] // 创建特定大小的数组[0, 1, 2...]
(arr) => arr.slice().sort(() => Math.random() - 0.5) // 随机打乱数组
Array.from({length: 5}).fill(item) // 创建特定大小的数组[item, item, item...]

CSS常用代码

超出省略

1
2
3
4
5
6
7
8
9
.line-camp( @clamp:2 ) {
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: @clamp;
-webkit-box-orient: vertical;
}

两端对齐

1
2
3
4
5
6
7
8
9
10
11
12
div {
margin: 10px 0;
width: 100px;
border: 1px solid red;
text-align: justify;
text-align-last:justify
}
div:after{
content: '';
display: inline-block;
width: 100%;
}

处理1px细线问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// transform + 伪类处理方案 (低版本可能会出现断裂)
.border_bottom {
overflow: hidden;
position: relative;
border: none!important;
}
.border_bottom:after {
content: ".";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background-color: #d4d6d7;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}

// box-shadow 替代方案 (颜色会变浅)
.border_bottom {
box-shadow: inset 0px -1px 1px -1px #d4d6d7;
}

git常用资源

标签功能

1
2
3
4
5
git tag #显示所有标签
git tag -l 'v1.0.*' #显示v1.0开头的标签
git tag -a -m 'some tip' #增加标签并展示
git show v1.0 #查看v1.0的信息
git push origin --tags #推送所有标签

分支功能

1
2
3
git checkout -b newBranch origin/oldBranch #以远程分支为基础创建新分支
git branch -D curBranch #删除现有分支
git merge newBranch #merge新分支到现有分支

远程常用功能

1
2
3
4
5
git pull #拉取所有信息到本地
git push #推送本地信息到远程
git remote -v #查看远程分支信息
git remote add upstream git@github.com:sfilata/gitskills.git #添加远程主机
git fetch #拉取远程主机信息

一个提升开发效率的CLI工具

用到的工具:

commander.js

安装
1
npm install command --save
实现

首先编写一个可执行的脚本文件,定为init-project.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env node

/**
* Module dependency
*/

const program = require('commander')
const path = require('path')
const vfs = require('vinyl-fs')
const chalk = require('chalk')
const fs = require('fs')

function pathMapObj(type, param) {
return {
'index': {
input: './demo/index.vue',
output: path.resolve(`./src/entries/${type}/pages/${param}`)
},
'actions': {
input: './demo/action/*',
output: path.resolve(`./src/entries/${type}/store/${param}`)
},
'api': {
input: './demo/api.js',
output: path.resolve(`./src/api/${type}`)
}
}
}

/**
*
* @param {输入路径} input
* @param {输出路径} output
* @param {类型} type
* @param {是否需要重命名} needRename
* @param {模块名} moduleName
*/

function readAndWrite(input, output, type, needRename, moduleName) {
vfs.src([input])
.pipe(vfs.dest(output, {}))
.on('end', function () {
console.log(chalk.green(`initializing ${type} file finished......`))
if (needRename) {
fs.renameSync(`${output}/api.js`, `${output}/${moduleName}.js`)
}
})
.resume()
}
program.version('1.0.0')
.option('-t --teacher [name]', 'init the teacher component')
.option('-s --student [name]', 'init the student component')
.option('-m --manager [name]', 'init the manager component')
.parse(process.argv)
let param = program.teacher || program.student || program.manager
if (param) {
let type = null;
if (program.teacher) {
type = 'teacher'
} else if (program.student) {
type = 'student'
} else if (program.manager) {
type = 'manager'
}
if (param.toString() === 'true') {
console.log(chalk.red('格式错误!缺少组件名参数'))
return
}
console.log(`The ${chalk.blue(param)} component will be inited on ${chalk.yellow(__dirname)}`)
console.log(chalk.yellow('initializing specified component......'))\

readAndWrite(pathMapObj(type, param).index.input, pathMapObj(type, param).index.output, 'index')
readAndWrite(pathMapObj(type, param).actions.input, pathMapObj(type, param).actions.output, 'actions')
readAndWrite(pathMapObj(type, param).api.input, pathMapObj(type, param).api.output, 'api', true, param)

} else {
console.log(chalk.red('格式错误!正确命令举例:node ./bin/init-project -t component-name'))
}

上面文件主要功能为读取demo文件夹的样例模板文件,并按照类型和模块名进行相应路径的输出,以达到自动初始化模块开发的功能,免去每次开发新功能时创建多个重复文件的苦恼

windows下存在问题,不识别脚本声明语句#!/usr/bin/env node,导致只能使用node来执行代码

在同级demo文件夹下放入要生成的样例文件。目前有四个文件,主要页面vue文件,action与store vuex所需文件,api(使用axio进行访问)文件。