• 图片按钮<input name="submit" type="image" value="ee" src="12.jpg" />

  • img下面有4px留白

  • 使用title属性显示提示信息

  • 空格:&nbsp;

  • <hr />color属性设置颜色

  • ie兼容性<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">

  • 只要是有src或href的HTML标签都有跨域的能力。

  • 网页中的空格转义字符&nbsp;在命令行中不能识别为正常的空格,会导致命令执行出错

  • 将dom元素关联自定义变量:加入属性data-*

    <img
    data-value=”31940”
    onclick={(e) => {
    console.log(e.target.dataset.value);
    }}
    />

  • dom元素绑定事件,传入当前元素

    如果你点我,我就会消失。

  • mongo:打开命令行

  • 进入数据库:use DBname。展示:show dbsshow collections

  • mongoimport mongoexport备份与恢复集合(collection)

    共同的相关配置:-d DBname -c COLname -h IPaddress:PORTname

    从filename导入:mongoimport [config] filename

    filename:mongoexport [config] -o filename

    导入数据要避免与原来的数据重复,先删除集合db.COLname.drop() 再mongoimport

  • MongoDB 数据库备份(mongodump)与恢复(mongorestore)

  • 命令行中打印变量print VARIABLE

  • 使用javascipt的数组迭代方法forEach map
    这样可以方便的操作字段名(field),如字段重命名、字段合并

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    db.getCollection('spaces').find({}).forEach(function(x) {
    if(x.in_company) {
    x.in_company = x.in_company.map(function(ele, i) {
    return {
    name: ele,
    website: x.in_company_url ? x.in_company_url[i] : null,
    }
    });
    delete x.in_company_url;
    db.spaces.save(x);
    }
    })
  • 加入表的关联:mongoose字段加入ref属性,查询时加入populate方法。

数据库操作

  • db.COLname.save()包含_id则为修改文档,不包含则与db.COLname.insert()功能相同

  • 查询时注意String(‘1’)与Number(1)的区别,在mongoose的保存save与更新update操作中,定义好Schema的字段类型后,则数字与字符串没有区别。

  • 查询不存在字段名或者字段的值为nulldb.COLname.find({"FIELD": null})

    相应的查询字段存在并且值为nulldb.COLname.find({"FIELD": {"$in":[null],"$exists":true}})
    查询存在该字段的文档{$exists: true}

  • 文档中的字段存储数组/对象时的查询:在文档{"fruits" : [ "apple", "pear", "orange" ] }

    字段的值为数组:
    找到数组中包含值:find({"fruits":"apple"})

    数组中包含多个值:find({"fruits":{"$all":["apple","banana"]}})

    数组中某个索引为某个值:find({"fruits.1":"orange"})

    精确查询,要求值相同并且顺序一致:
    find({"fruits":["apple","orange","pear"]})

    字段的值为对象数组时:使用精确匹配时,只会找出字段的值相等并且顺序一致的文档。
    要求包含某些键值对,注意与字段的值为对象时查询的区别:
    find({ "name.first":"joe", "name.middle":"bush" })

安全策略

设置用户权限

  • mongod --auth开启权限认证,再加入用户分配权限
  • TLS/SSL传输加密
  • 数据库定时备份
  • 不使用mongodb默认端口,防止端口扫描
  • 不需要公网连接时,bind_ip只允许本地访问

mongoose

mongoose的model名称为首字母大写时,存到mongodb时会自动首字母小写

mongodb版本6安装

安装MongoDB Community Server
安装MongoDB Shell

  • React.Children.map(this.props.children, () => { …… })

  • 改变state不使用push方法而是setState

  • ES6语法const props = { ...this.props };

  • 组件自定义背景,在父组件位置设置style属性,然后在子组件里面继承style属性;

  • setState是异步的,不会马上更新state。setState有callback函数

  • react-router的onEnter设置路由权限

  • 当前地址:Location
    跳转页面:useNavigate

  • 使用div模拟textarea:属性contentEditable="plaintext-only"onInput={this.emitChange}this.inputRef.innerHTML获取输入内容。

    1
    2
    3
    4
    5
    6
    7
    <div
    className="input_content"
    onInput={this.inputChange}
    contentEditable="plaintext-only"
    ref={(inp) => { this.inputRef = inp }}
    onKeyDown={this.onKeyDown}
    />

    新版ref写法ref={this.inputRef}

  • 键盘事件

    onKeyDown = (e) => {
    console.log(e.key);
    }

状态提升

你一定听说过变量提升,函数提升,那么状态提升是什么呢?

首先你得了解双向绑定和单向数据流,双向绑定中,数据可以在不同的组件之间实现共享,这样做的确有很大的好处,但是在react中,不推荐使用双向绑定,而是使用状态提升的方式。

状态提升:state推崇单向数据流,数据从父组件通过props流向子组件,如果你在子组件中,需要修改state来和其他子组件共享数据更新,你需要使用回调函数给使数据更新给父组件,然后从父组件流向其他的子组件,这样做是保证数据有单一的来源。

如果子组件和子组件之间任意共享数据,那么,后期维护会比较痛苦,特别是找bug的时候。

看一个状态提升的例子吧。

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
class Child extends React.Component {
constructor(props) {
super(props);
}
handleChange = (e) => {
this.props.upDateValue(e.target.value);
}
render() {
const {name, value} = this.props;
return (
<div>
<p>{name}:</p>
<input
value={value}
onChange={this.handleChange}
/>
</div>
);
}
}

class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {value: '', name: ''};
}
upDateValue = (value) => {
this.setState({value: value})
}
render() {
const {value} = this.state;
return (
<div>
<Child name="组件1" value={value} upDateValue={this.upDateValue} />
<Child name="组件2" value={value} upDateValue={this.upDateValue} />
</div>
);
}
}
ReactDOM.render(
<Demo />,
document.getElementById('root')
);
- 传递属性给子组件

const childrenWithProps = React.Children.map(this.props.children,
child => React.cloneElement(child, {
equityRate: this.publishTasks,
}),
);

this.context

  • this.context用法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //在父组件中包含方法
    getChildContext() {
    return {
    USER: this.state.USER,
    };
    }
    Parent.childContextTypes = {
    USER: PropTypes.object,
    };
    //在子组件中
    Child.contextTypes = {
    USER: PropTypes.object,
    };
    constructor(props, context)

Atom快捷键

  • Ctrl+shift+m预览markdown

VScode快捷键

  • Ctrl+shift+v预览markdown

  • string操作不改变原string,只会返回新string。Buffer只改变原Buffer。
  • bin => dup
    1
    2
    var dup = new Buffer(bin.length);
    bin.copy(dup);
  • 附件上传
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const uploadFile = (req, res, next) => {
    //生成multiparty对象,并配置上传目标路径
    var form = new multiparty.Form({uploadDir: './public/files/'});
    //上传完成后处理
    form.parse(req, function(err, fields, files) {
    var inputFile = files.file[0].path;
    console.log('inputFile', inputFile);
    res.writeHead(200, {'content-type': 'text/plain;charset=utf-8'});
    res.end(inputFile);
    //res.end(util.inspect({files: inputFile}));
    });
    };
  • 实现文件下载
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    router.get('/file/:fileName', function(req, res, next) {
    var fileName = req.params.fileName;
    var filePath = path.join(__dirname, fileName);
    var stats = fs.statSync(filePath);
    if(stats.isFile()){
    res.set({
    'Content-Type': 'application/octet-stream',
    'Content-Disposition': 'attachment; filename='+fileName,
    'Content-Length': stats.size
    });
    fs.createReadStream(filePath).pipe(res);
    } else {
    res.end(404);
    }
    });
    前端<a>标签加上download属性后就可以下载了

服务器操作

  • pm2 list
  • pm2 restart 1
  • pm2 start <path/to/app.js>

Yarn

  • yarn add [package]
  • yarn add [package]@[version]
  • yarn add [package]@[tag]
  • yarn upgrade [package]
  • yarn remove [package]
  • yarn install

  • Boolean && 变量
  • Boolean || 变量可以用来设置默认值
  • a.indexOf(b)a为字符串或者数组
  • a.toFixed(2)a类型为number,保留小数
  • toString()可以判断对象的类型。number.toString
  • -a可以将a转化为number类型
  • 正则表达式//gi,g表示全局搜索,i表示忽略大小写
  • js不支持负向零宽断言(?<=aaa)
  • Math.floor()向下取整,Math.ceil()向上取整,Math.round()四舍五入。
  • arr.sort()由大到小排序后面减去前面。
  • substr() 方法返回一个字符串中从指定位置开始到指定字符数的字符。
    不改变原数组,字符串
    str.substr(start[, length])
  • Array.prototype.slice()
    String.prototype.slice()
    slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
  • Array.prototype.splice()

array.splice(start[, deleteCount[, item1[, item2[, …]]]])

splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

返回值

由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。
- Array.forEach(arguments, func())对非数组序列进行forEach处理
- Array(<len>).fill(<value>) 填满数组

numberArray.sort(function(a,b){  //6,5,4,3,2,1
    return b-a;
})
  • 数组操作: shift(),unshift(),pop(),push()。改变原数组。

  • 箭头函数的this,指向其定义位置的this。

  • this总是指向函数的直接调用者(而非间接调用者),在DOM事件中,this指向定义这个事件的DOM对象;

  • t=setTimeout(fun(), N毫秒);clearTimeout(t)t=setInterval();clearInterval(t)

  • async与await

    var start = async function () {
    for (var i = 1; i <= 10; i++) {
    console.log(当前是第${i}次等待..);
    await sleep(1000);
    }
    };

  • e.preventDefault();

对象处理

  • Object.keys(obj)得到对象的可枚举属性
  • delete Obj.prop删除对象属性
  • 简单的拷贝:const a = {};``a = { ...ArrObj }Object.assign({}, Obj)
  • 字符串与对象的转换:JSON.stringify(json)JSON.parse(string)。Array也是Object类型
  • 字符串变量d用作对象属性名:{ [d]: !this.state[d] }

作用域

  • if块级作用域在ES5与ES6中不同
  • const a = func; 与function a(){}的变量提升方式不同;
  • for循环中let 与var i = 0,在函数中不同

原型继承

  • 对象的constructor属性指向它的构造函数。对象的__proto__属性指向上一级的原型对象。构造函数的prototype等于其生成对象的__proto__。

  • 必须显式地设置原型才能确保动态的继承,将B设置为A的原型链: A.prototype = new B;

  • 将构造器B属性传给A作为A的自身属性

    function A (a, b) {
    B.call(this, c, d);
    this.machine = mach || “”;
    }

  • A为函数:A.prototype={ constructor: A, __proto__: 基本prop }

Web APIs

  • 在chrome中加入断点:在源码中加入debugger
  • 前端全局对象window,node.js全局对象global。全局对象可以用来设置全局变量window.abc
  • window.location获取当前页面网址信息,可进行页面跳转
  • fetch跨域加上{ mode: ‘no-cors’ },response类型为opaque,status为0。或者使用fetch-jsonp
  • 赋值localStorage.abc = string,数字存入localStorage后变为string
  • URLSearchParams
  • es6 array新方法

样式

  • border: 5px solid red;

  • margin: top left-right bottom;

  • display:inline-block;

  • cursor: point;

  • 设置边框阴影box-shadow: inset 0 0 2em blue;

  • 图文并排

    .dom {
    background:url(‘/images.jpg’) no-repeat;
    padding-left:
    width:
    }

  • inline元素设置高度: {display: inline-block;}再设置 width height

  • a {color: #000;} * 未被访问的链接 *

  • a:visited {color: #3ac1bd;} * 已被访问的链接 *

  • a:hover {color: #3ac1bd;} * 鼠标指针移动到链接上 *

  • a:active {color: #3ac1bd;}

  • a{ text-decoration: none; } 去掉链接的下划线

排版

  • position: relative - absolute;

  • 填满整个元素:父元素设置高度,子元素height: 100%

  • css度量运算calc(100% - 36px)

  • hover显示新元素

    .parent { position: relative; .child1, .child2 { height: 100px; width: 100px; } .child2 { display: none; background: rgba(230, 230, 230, 0.9); } } .parent:hover .child2 { display: block; position: absolute; top: 0; cursor: pointer; }

对齐

  • margin: auto;

  • 水平对齐

    父元素中设置text-align: left | right | center | justify | inherit;

  • 垂直对齐:

    子元素为inline,table-cell或者inline-block时vertical-align: top | text-top | middle | bottom | text-bottom;table-cell与inline-block中middle显示不同

    block元素中的文字line-height设置为该元素height

Flex

  • 子元素的float、clear和vertical-align属性将失效。
  • flex-direction: row | row-reverse | column | column-reverse;
  • flex-flow: flex-direction | flex-wrap;
  • justify-content: flex-start | flex-end | center 水平对齐方式
  • align-items: flex-start | flex-end | center 垂直对齐方式
  • 多根轴线align-content: flex-start | flex-end | center | space-between | space-around | stretch;
  • 保留空白符white-space: normal|pre|nowrap|pre-wrap|pre-line|inherit;

Css单位

  • vh:屏幕比例。px:像素。rem根元素的字体大小

Css选择器

  • .class #id element
  • 直接子元素:>
  • 选择器之间,表示and

进入项目文件根目录

git init将该文件夹加入git的管理之中, 并新建了一个.git/文件夹

新建.gitignore文件让git忽略不需要同步的文件夹/文件。

git add ..目录——就是当前目录加入git暂存区域(staging area)。

git commit -m "first commit"将声明区的文件加入到本地仓库

git remote add origin git@github.com:ABCD.git添加远程仓库的路径,并命名为origin,git@ABCD.git为使用ssh协议同步,https://ABCD.git使用https协议同步。ssh同步需用额外的配置,但是之后不需要输入密码,而且安全性更高。https协议需要每次输入用户名和密码,想要省略输入密码,就需要明文保存在本地电脑上,安全性低。

git push -u origin master将本地仓库推送到名为origin的远程仓库的master分支(branch)

额外参考

配置ssh密钥到git服务器

cd ~/.sshls查看该目录下是否之前已经生成密钥id_dsa.pub公钥文件和id_dsa私钥文件,文件名可能id_dsa可能是别的名字,但都是成对出现,其中公钥以.pub结尾。
如果没有就可以ssh-keygen来创建密钥对。该程序在 Linux/Mac 系统上由 SSH 包提供。中途需要一些额外的配置,记住输入的密码即可,其他的配置可以按enter使用默认的方式。
生成之后复制公钥id_dsa.pub的内容,在git服务器上添加SSH keys的位置添加即可。ps:cat id_dsa.pub打印公钥id_sda.pub的内容。

修改远程仓库的地址

git remote set-url <name> <newurl>默认为origin,这样就可以将已有的https远程仓库地址修改为<newurl>——ssh的新地址了。

创建博客,记录一些事,可能以后用得着。

0%