Open SunXinFei opened 6 years ago
webpack的output下面有两个路径,一个path,一个是publicPath,其实区别还是很大的,首先path这个不需要特别多的解释,就是编译输出的项目路径,如下图所示。但是实际放置到服务器中,不一定是服务器的根目录下的dist文件夹,有可能是放置在服务器的wwww文件夹下面,这时候就需要我们设置下publicPath文件夹的输出路径。
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),//项目输出到根目录下面的dist文件夹中,html中的路径显示为src="app.bundle.js"
publicPath:'/wwww/' //指定的外层目录,html中的路径显示为 src="/wwww/app.bundle.js"
},
平时在写readme.md的时候,可能会使用树状的目录结构,比如
|--
|-- .gitignore
|-- package.json
|-- README.md
|-- webpack.common.js
|-- webpack.dev.js
|-- webpack.prod.js
|-- prod-dist
| |-- index.html
| |-- component1
| | |-- index.5a006a90.js
| | |-- index.5a006a90.js.map
| |-- component2
| |-- index.5a006a90.js
| |-- index.5a006a90.js.map
|-- src
|-- platform-templete
| |-- index.html
|-- platform-widgets
|-- component1
| |-- index.js
| |-- style.css
|-- component2
|-- index.js
|-- style.css
npm install mddir -g
mddir
即可得到一个directoryList.md文件
windows自带的tree命令可以实现打印树形目录结构,但是没有找到好的方法忽略node_modules这个文件夹,我使用的是一个npm包mddir,安装成功后,在想要的文件夹中运行命令mddir
,就会在目录中生成一个directoryList.md,可以直接复制出来使用。比如npm install -g hexo
会放置到全局的变量,这种情况下,在命令行里可以直接执行hexo -v
这样的命令,但是如果只是运行npm install hexo
会安装到当前项目的node_modules文件夹当中,这种情况下需要这么运行node_modules/.bin/hexo -v
即可,就是说node_modules/.bin/模块名
。
安装npm install rimraf -g
运行rimraf node_modules
快速移动光标
i: 插入光标前一个字符
I: 插入行首
a: 插入光标后一个字符
A: 插入行未
o: 向下新开一行,插入行首
O: 向上新开一行,插入行首
df -lh
显示本地文件系统信息
du -h --max-depth=1
查看文件夹下一层目录 体积
mysql -u用户名 -p密码 -h远程数据库IP地址 -P端口 -D数据库名
sudo vi /private/etc/hosts
输入o进入编辑状态;
esc退出编辑,:wq 保存 , :q 退出
停止服务:nginx -s stop
启动服务:nginx
重启服务:进入nginx可执行目录sbin下,输入命令./nginx -s reload
即可
重启服务:nginx -s reload
查看nginx配置文件目录:open /usr/local/etc/nginx/
查看nginx被安装到的目录:open /usr/local/Cellar/nginx
测试nginx配置:nginx -t
查看端口占用情况:lsof -i:端口号
查看nginx进程:ps -ef|grep nginx
杀死nginx进程:kill -QUIT 进程号
sudo /etc/init.d/nfs-kernel-server start
sudo /etc/init.d/nfs-kernel-server restart
这个跟php.ini中开启了opcache有关系,可以避免反复编译带来的性能消耗。所以开发状态下关闭即可,但是修改完ini文件之后,记得重启php-fpm和nginx
tar -cvf MyCard.tar ./vue-webpack-demo/src/pages/Home/components/MyCard/
sudo ln -s /data0/tui/CMS/storage/app/public /data0/tui/CMS/public/storage
自定义代理规则的设置语法规则如下,记得重启:
ffmpeg -i http://play2.kandian.360.cn/vod_xinwen/vod-media/1160007_3029687_20160725140508.m3u8 "文件名.mp4"
需求:在一行中有两段文字,左侧是昵称,右侧为评论,昵称正常展示,右侧评论吃掉剩余长度,超出就省略号
<div class="card-comment">
<div class="nickname">
<div class="nickname-ellipsis">{{comment.nickname}}</view>
</div>
<div class="comment">{{comment.comment}}</view>
</div>
.card-comment {
font-size: 0.26rem;
font-family: PingFang-SC-Regular ;
display: flex;
overflow: hidden;
padding: 0 0.3rem;
}
.card-comment .nickname {
color: #000000;
max-width: 5rem;
}
.card-comment .nickname-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.card-comment .comment {
color: #999999;
margin-left: 0.2rem;
flex: 1 1 auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 2rem;
}
解决在使用animation动画时,页面出现抖动的问题 给使用动画的元素加上-webkit-backface-visibility: hidden;
优先级: !important > 内联样式 > ID选择器 > 类选择器 = 伪类选择器 = 属性选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
解决方案:将flex:1元素设置overflow: hidden;或者min-width: 0;即可,这里注意一点 如果是flex:1元素N层的嵌套,那么这N层flex:1元素都需要设置。
display:inline-block的元素之间会有一个字符的间隙,这个间隙导致了最后一个会掉下来。 解决方法: 1、给父元素设置font-size:0;
<div class="title">
<span>用户表测试_动态汇总</span>
<label>某个checkbox</label>
</div>
这个要实现span和label的flex布局,然后space-between,在火狐和Chrome和IE11中可以完美显示,只要加上如下代码:
.title {
display: flex;
justify-content: space-between;
}
但是在IE10中会出现span中文本过长但不折行的现象。 解决方案stackoverflow连接并且其他浏览器不受影响
span{
display: block;
max-width: 100%;
flex-shrink: 1;
}
1.使用flex
.box {//外层元素
display: flex;
align-items: center; //垂直居中
justify-content: center;//水平居中
}
2.还有一种外层flex,内层margin:auto
.box {//外层元素
width: 200px;
height: 200px;
display: flex;
}
.center {//内层元素
width: 100px;
height: 100px;
margin: auto;
}
3.绝对定位(不需知道内层/外层元素的宽和高)
.center {//内层
position:absolute;
left:50%;
top:50%;
transform: translate(-50%,-50%);
}
4.绝对定位(不需知道内层/外层元素的宽和高,需设置内层的宽高)
.box {//外层
width: 200px;
height: 200px;
background:#fff;
position:relative
}
.center{//内层
width:100px;
height:100px;
left:0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
position:absolute;
background:#000;
}
5.绝对定位(需知道内层的宽高)
.center{ //内层
width:100px;
height:100px;
position: absolute;
left: 50%;
top:50%;
margin-left:-50px; //内层元素的一半
margin-top: -50px;
}
6.绝对定位(需要知道外层/内层元素宽和高)
.center {//内层
position: absolute;
width: 100px;
height: 100px;
left: 50px;//外层元素一半减去center元素一半
top: 50px;
}
这种情况发生的条件有三个: 1、父标签 position属性为relative; 2、问题标签无position属性(不包括static); 3、问题标签含有浮动(float)属性。
.flow-node-modal .ivu-modal {
@marginVal : 20px; //这里使用了变量
margin: @marginVal;
top:0;
.ivu-modal-content {
height: calc(~"100vh - "@marginVal*2); //注意!,这里的写法,一般的写法less解析calc会有问题
}
}
sass的写法为:
height: calc(100vh - #{$marginVal*2}); //注意!,这里的写法,一般的写法sass解析calc会有问题
text-align具有继承性,给祖先元素添加,即可实现内部行内元素的水平居中; vertical-align属性只对行内元素有效,给需要垂直居中的内容元素添加,父级元素需要添加line-height,如果内容元素只有一个,可以不添加vertical-align:middle也可以垂直居中。 块级元素,给定宽度使用margin:0 auto,水平居中,
拜读了大漠的两篇文章写得还是非常系统的: Vue 2.0学习笔记:Vue的transition Vue 2.0学习笔记:Vue的animation
一种常见需求:有n个宽度相同的卡片,需要间距相等,从左到右铺满内容区域,直接用flex的space-between会导致,不满一行的数量卡片,布局异常。 解决方案:用N个空元素占位
/**
* 填充N个空dom,来解决flex中space-between布局的问题,
* 宽度为卡片宽度,N为填满一行的数量
* @returns
*/
const getEmptyDom = () => {
let emptyFiles = []
for (let i = 0; i < EmptyFilesLength; i++) {
emptyFiles.push(
<div key={i} className={styles.flexEmpty} />
)
}
return emptyFiles
}
<div className={styles.cardContent}>
<Card size='small' bordered={false} title='Inner Card title' className={styles.innerCard} >
Inner Card content
</Card>
<Card size='small' bordered={false} title='Inner Card title' className={styles.innerCard}>
Inner Card content
</Card>
{
// 填充N个空dom,来解决flex中space-between布局的问题
getEmptyDom()
}
</div>
.cardContent{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: flex-start;
align-content: flex-start;
.flexEmpty{
width: 33%;
border: 1px solid transparent;
margin: 0;
visibility: hidden;
height: 0 !important;
}
.innerCard{
width: 33%;
margin-bottom: 10px;
}
}
window.addEventListener('click', ()=>{
console.log(1)
}
)
window.addEventListener('click', ()=>{
console.log(2)
}
)
window.onclick = ()=>{
console.log(3)
}
window.onclick = ()=>{
console.log(4)
}
window.click();//1 2 4
简而言之,on会进行覆盖,而addEventListener会进行无限次添加,不会覆盖。
var a = [{id:1,name:1},{id:2,name:2},{id:3,name:4}];
var result = a.find(function(a,b,c){
if(a.id == 3){
return a;
}
});
console.info(result);
result = a.filter(function(a, b, c){
if(a.id == 2){
return a;
}
});
console.info(result[0]);
a.forEach(function(a, b, c){
if(a.id == 3){
result = a;
return;
}
});
console.info(result);
a.map(function(a,b,c){
if(a.id == 2){
result = a;
return;
}
});
console.log(result);
a.some(function(a){
if(a.id == 3){
result = a;
return;
}
});
console.log(result);
var b = a.entries(),
c;
while (!(c = b.next()).done) {
if (c.id == 3) {
result = c;
break;
}
}
console.log(result);
1.首先查看ssh是否存在
$ cd ~/.ssh
$ ls
看一下有没有id_rsa和id_rsa.pub(或者是id_dsa和id_dsa.pub之类成对的文件),有 .pub 后缀的文件就是公钥,另一个文件则是密钥。
2.命令创建ssh密钥
ssh-keygen -t rsa -C "your_email@youremail.com"
2.1 如果需要创建不同的ssh,那么中间一步需要输入自己想要的路径地址,而不是直接回车
3.查看密钥
cat ~/.ssh/id_rsa.pub
4.将密钥复制粘贴到网站对应位置即可
ssh-keygen -t rsa -C "YOUR_EMAIL@YOUREMAIL.COM" -f ~/.ssh/zidingyi
运行命令创建config文件
vim ~/.ssh/config
根据项目进行配置
# default
Host git
HostName domain.com
User xinfei
IdentityFile ~/.ssh/id_rsa
# two
Host github
HostName github.com
User xinfei
IdentityFile ~/.ssh/id_rsa_github
测试是否成功
ssh -T git@github.com
放弃所有更改:git checkout .
放弃某个文件:git checkout -- filename
git remote add origin2别名 git@github.com:xxxxxx.git git push origin2别名 master 如果添加-u的参数,则会将该服务地址为默认push地址
git checkout -b test git push origin test 这样远程仓库中也就创建了一个test分支
git branch -r #查看远程所有分支
git branch #查看本地所有分支
git branch -a #查看本地及远程的所有分支,如下图
git fetch #将某个远程主机的更新,全部取回本地:
git checkout 分支 #切换分支:
git push origin -d 分支名 #删除远程分支:
git branch -d 分支名 #删除本地分支
git remote show origin #查看远程分支和本地分支的对应关系
git remote prune origin #删除远程已经删除过的分支
git clone giturl 项目名称 # git clone 不包含外层文件夹
# 设置
git config --global alias.gb "branch --show-current"
# 使用
git gb
#设置
git config --global alias.cm "commit -m"
# 使用
git cm 'fix: 123'
# 设置
git config --global alias.c- "checkout -"
#使用
git c-
第一步: git log --pretty=oneline 查看当前提交的日志
第二步: git reset --soft XXX XXX是commitID(d6cdbba417....) 回退当前工作空间的上一个版本,并且保留代码更改
第三步: git log --pretty=oneline 再次查看当前提交的日志,确认是否成功撤销,当然,你也可以不看,基本上都会成功,保险一下,看看呗
第四步: git push origin BranchName --force 强制提交当前版本号,以达到撤销版本号的目的.必须添加参数force进行强制提交,否则会
## git撤销merge(注意 ,可能会导致本地某个分支,覆盖另一个分支
第一步 git reflog 查看提交日志
第二步 git reset --hard 【merge前的版本号】
git reset --hard origin/main 这个命令会将你的本地main分支重置为远程仓库origin上的main分支的状态。--hard选项会使你的工作目录中的文件匹配远程分支的状态,这意味着所有本地的更改和提交都会被丢弃。
npm ERR! Unexpected end of JSON input while parsing near '...ncies":{"inherits":"~'
npm cache clean --force
总结下来,多为网络环境导致的一些包依赖并没有下载成功,真正解决方案为: 1.删除npm cache
错误:console控制台输出会有惰性问题,在查看对象、数组这种引用型变量时,会出现控制台输出与运行时的值不正确的问题 解决方法:使用console.log(JSON.stringify(obj))或者alert 参考依据:Is Chrome's JavaScript console lazy about evaluating arrays? eg:
var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);
将以上语句在console控制台输出,会发现展开之后不同的结果,原因大致为控制台输出的堆区对应的地址的数据,会导致引用类型的变量,在展开的时候会出现执行后的值,如图:
按照官网的配置babel
npm install babel-plugin-import --save-dev
{
"plugins": ["transform-vue-jsx", "transform-runtime",["import", {
"libraryName": "iview",
"libraryDirectory": "src/components"
}]]
}
注意main.js修改如下,不然会有iview is not defined的错误信息:
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from 'components/app.vue';
import Routers from './router.js';
// import iView from 'iview'; <=注释掉
import 'iview/dist/styles/iview.css'; //<=保留
Vue.use(VueRouter);
// Vue.use(iView);<=注释掉
//<=在此页面增加或Vue页面中添加均可
import {Input,Dropdown } from 'iview';
Vue.component('Input', Input);
//<=增加
// The routing configuration
const RouterConfig = {
routes: Routers
};
const router = new VueRouter(RouterConfig);
new Vue({
el: '#app',
router: router,
render: h => h(App)
});
iview按需加载之前后比较,明显降低
npm install webpack-bundle-analyzer --save-dev
在webpack的dev配置文件中配置一下即可
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
plugins: [
new BundleAnalyzerPlugin(),
]
然后npm run dev
即可看到效果。
注意我箭头指示的地方,名称不同的原因即为vue-router中的映射代码,特殊注释命名
const Project = () => import( '@/components/Project')
const Flow = () => import(/* webpackChunkName: "flow" */ '@/components/Flow')
这样,我们可以通过该工具来分析哪个文件是最大的来有目的的优化 !!注意,如果没有在entry中指定,那么chunkName会等于chunkId,即为0.chunckhash.js 懒加载配置完,对比明显
如
<script type="text/javascript" src="js/test0.js"></script>
<script type="text/javascript" src="./js/test1.js"></script>
<script type="text/javascript" src="/js/test2.js"></script>
假如index.html在template文件夹下的话,访问index.html为127.0.0.1:80/template/index.html test0和test1都表示index.html所在的当前文件夹下,即为127.0.0.1:80/template/js/test0.js 而test2表示服务根目录下的js文件夹,即为127.0.0.1:80/js/test2.js
解决方案:在package.json中的dev指令中加入--host 0.0.0.0
即可
webpack-dev-server --host 0.0.0.0
参考文献-github
注意:
如果修改webpack的config的文件修改host均不起作用,或会导致ip写死,本地127.0.0.1无法正常访问
function getIPAdress(){
var interfaces = require('os').networkInterfaces();
for(var devName in interfaces){
var iface = interfaces[devName];
for(var i=0;i<iface.length;i++){
var alias = iface[i];
if(alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal){
return alias.address;
}
}
}
}
//this.inventoryChart为echarts实例
//this.option 为echats实例的配置项
//给本页面的echart添加click事件
bindEventForChart() {
//获取echats的canvas区域,并绑定click事件
this.inventoryChart.getZr().on("click", params => {
const pointInPixel = [params.offsetX, params.offsetY];
if (this.inventoryChart.containPixel("grid", pointInPixel)) {
//将点击区域的横轴像素值转化成x轴index
let xIndex = this.inventoryChart.convertFromPixel(
{ seriesIndex: 0 },
[params.offsetX, params.offsetY]
)[0];
//将x轴坐标index,转化成对应像素值
let offsetX = this.inventoryChart.convertToPixel(
{ xAxisIndex: 0 },
this.option.xAxis.data[xIndex].value
);
//处理点击事件的逻辑
this.handleEchartClickEvent(xIndex, offsetX);
}
});
},
echo M('explorer_class')->getLastSql();
方法有很多可以搜下,这里说一种比较简单的命令:
code .
即可touch update-demo.sh
#!/bin/bash
cd /data/react-grid-layout-between
sudo git pull
npm install
npm run build
sudo rm -rf /data/wwwroot/demo.sunxinfei.com/*
sudo cp -r /data/react-grid-layout-between/build/* /data/wwwroot/demo.sunxinfei.com/
echo "********************************"
echo "*********** complete ***********"
echo "***** $(date "+%Y-%m-%d %H:%M:%S") *****"
echo "*********** $0 ************"
echo "********************************"
sh update-demo.sh
如果想实现github上push代码,页面实时更新,就需要借助webhook这个功能,它会提供代码更新的接口,比如push,这样我们就可以在服务器端进行监听,然后执行相应的命令。
/usr/local/nginx/conf/vhost
# 意思是我们监听 http://test.com/webhook 请求,转到本地服务器的7777端口
server {
listen 80;
server_name test.com;
location /webhook {
proxy_pass http://127.0.0.1:7777;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
# root html;
# index index.html index.htm;
}
}
/usr/local/nginx/sbin/nginx -s reload
// 如果报错github-webhook-handler模块找不到,就打开下面这句注释
// module.paths.push('/root/.nvm/versions/node/v8.12.0/lib/node_modules');
var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: '/webhook', secret: '设置的github中的密钥' })
function run_cmd(cmd, args, callback) { var spawn = require('child_process').spawn; var child = spawn(cmd, args); var resp = "";
child.stdout.on('data', function(buffer) { resp += buffer.toString(); }); child.stdout.on('end', function() { callback (resp) }); }
http.createServer(function (req, res) { handler(req, res, function (err) { res.statusCode = 404 res.end('no such location') }) }).listen(7777)
handler.on('error', function (err) { console.error('Error:', err.message) })
handler.on('push', function (event) { console.log('Received a push event for %s to %s', event.payload.repository.name, event.payload.ref) run_cmd('sh', ['./update-demo.sh',event.payload.repository.name], function(text){ console.log(text) }); })
handler.on('issues', function (event) { console.log('Received an issue event for %s action=%s: #%d %s', event.payload.repository.name, event.payload.action, event.payload.issue.number, event.payload.issue.title) })
4. 在github的的对应项目中,打开setting选项,进入webhooks标签,
Payload URL填写http://test.com/webhook Content type 修改为 application/json Secret设置自己的密钥之后,记得同步修改到前面创建的deploy.js中。
5. 准备工作都已经做完,我们可以实验是否已经打通,我们在服务器端的deploy.js目录下运行`node deploy.js`,我们更新下代码或者打开网址 `http://test.com/webhook`,查看是否服务器端有console.log输出。
6. 现在我们需要[pm2](https://pm2.io/doc/en/runtime/overview/?utm_source=pm2&utm_medium=website&utm_campaign=rebranding),因为目前该deploy的node脚本没有在服务器端后台运行。我们需要用pm2进行进程管理。
npm install pm2 -g pm2 start deploy.js
查看log
pm2 logs appName --lines 1000
/usr/local/nginx/conf
进入该文件夹下面,修改nginx.conf文件,
server {
listen 80 default;
rewrite ^(.*) https://github.com/SunXinFei permanent;
}
server {
listen 80;
server_name aaa.com;
*******省略其他配置
}
保存,重启nginx 该配置可以满足ip地址访问的时候,重定向至其他页面,如果是想域名访问的话,需要配置host,将aaa.com 指向 ip,即可用aaa.com访问原来的页面
sudo npm uninstall npm -g
sudo rm -rf /usr/local/lib/node /usr/local/lib/node_modules /var/db/receipts/org.nodejs.*
sudo rm -rf /usr/local/include/node /Users/$USER/.npm
sudo rm /usr/local/bin/node
sudo rm /usr/local/share/man/man1/node.1
sudo rm /usr/local/lib/dtrace/node.d
验证卸载:
node -v
npm -v
VS Code Counter 统计项目代码行数,区分注释、空行以及有效代码行,只需要安装后,右击文件夹即可 Live Server一件启动web服务
什么是徽标?如
徽标生成的网址一般用如下网站:
https://shields.io/
https://badgen.net/
https://forthebadge.com/
https://badge.fury.io/
https://github.com/boennemann/badges
网站会按照你的参数生成你所需要的徽标样式,例如
![webpack version](https://img.shields.io/badge/webpack-4.1.1-blue.svg)
将该链接添加到ReadMe中即可
If the right-click -> copy is not available you could try:
1 - Right-click the object and select "Store as global variable"
2 - The console will print the new variable's name, for example:
//temp1
3 - Type:
copy(temp1)
The object is now available in your clipboard.
有一个有趣的回答:
- 进程=火车,线程=车厢线程在进程下行进(单纯的车厢无法运行)
- 一个进程可以包含多个线程(一辆火车可以有多个车厢)
- 不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
- 同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
- 进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
- 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
- 进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
- 进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-"互斥锁"
- 进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”
这里直接抛出结论:Object的属性遍历顺序如果key是数字会按照数字先排序,字母或数字加字母类的key则按照原有顺序输出。 所以如果定义Object定义key尽量不要用数字防止后期出现顺序问题。
let aaa = {
'2b':'bbb',
'1a':'aaa',
}
Object.keys(aaa).forEach(k=>{
console.log(k) //2b 1a
})
//这里顺序会有问题
let aaa = {
'2':'bbb',
'1':'aaa',
}
Object.keys(aaa).forEach(k=>{
console.log(k) //1 2
})
let aaa = {
'b':'bbb',
'a':'aaa',
}
Object.keys(aaa).forEach(k=>{
console.log(k) //b a
})
"dependencies": {
"foo": "1.0.0 - 2.9999.9999",
"bar": ">=1.0.2 <2.1.2", 必须大于等于1.0.2版本且小于2.1.2版本
"baz": ">1.0.2 <=2.3.4", 必须大于1.0.2版本且小于等于2.3.4版本
"boo": "2.3.1", 必须匹配这个版本
"boo": "~2.3.1", 约等于2.3.1,只更新最小版本,相当于2.3.X,即>=2.3.1 <2.4.0
"thr": "2.3.x",
"boo": "^2.3.1", 与2.3.1版本兼容,相当于2.X.X, 即>=2.3.1 < 3.0.0,不改变大版本号。
"qux": "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0",
"asd": "http://asdf.com/asdf.tar.gz", 在版本上指定一个压缩包的url,当执行npm install 时这个压缩包会被下载并安装到本地。
"til": "~1.2",
"elf": "~1.2.3",
"two": "2.x",
"lat": "latest", 安装最新版本
"dyl": "file:../dyl", 使用本地路径
"adf": "git://github.com/user/project.git#commit-ish" 使用git URL加commit-ish
}
_.isEmpty(0) // true
const aaa = {a: null}
_.get(aaa,'a', '-') // null
获取url中的?号后的参数
防抖与截流
关于防抖(debounce) :在事件触发后的n秒之后,再去执行真正需要执行的函数,如果在这n秒之内事件又被触发,则重新开始计时。常见的操作就是搜索,中间不断的输入,我们都可以忽略,只获取最后停止输入的时候,才去请求后端。。 节流(throttling):规定好一个单位时间,触发函数一次。如果在这个单位时间内触发多次函数的话,只有一次是可被执行的。想执行多次的话,只能等到下一个周期里。常见的操作比如滚动事件,每隔n毫秒,我们去请求,或者拖拽,每隔n毫秒改变dom的位置。还比如resize窗口。 参考:
el.dataset
el.dataset可以获取DOM元素中绑定的data-的属性值,比如
el.dataset-index 即为index的值
JavaScript中 ‘+’ 号
有时阅读源码,会在代码中看到在某个元素前使用 ‘+’ 号,这个操作是将该元素转为Number类型,如果转换失败,那么将得到 NaN。
所以 +new Date 将会调用 Date.prototype 上的 valueOf 方法,而根据 MDN ,Date.prototype.value 方法等同于 Date.prototype.getTime()。所以一下代码效果相同:
JS中的'~'号
~是位非运算符,
~-1 === 0
表示true; 所以这个符号常用来搭配 indexOf 方法一起使用,比如:Cannot read property 'forEach' of null/undefined
??
有效的防止属性的值如果为空字符串或false或0箭头函数
箭头函数的this其实就是包裹它的第一个非箭头函数的函数的this值。因为箭头函数内部没有this。 如果对一些函数比如类内部指向有疑问,Babel转ECMA5看下即可清晰看出箭头函数内this指向。
构造函数
在JavaScript构造函数中:如果return值类型,那么对构造函数没有影响,实例化对象返回对象;如果return引用类型(数组,函数,对象),那么实例化对象就会返回该引用类型;