文章目录
学习笔记(3)
定位问题
-
最近赶项目,遇到了无法请求后端数据问题,页面重定向,经过核查后发现是自己的重定向代码,因为catch里面重定向前面有个toast导致自己一直认为这是其他地方做了处理导致重定向,接下来定位catch问题,
无法请求后端数据–检查后端接口是不是正确–最简单的是直接把请求网址放到浏览器上检查–结果404…–后端问题(没把这个接口布到服务器上)
charles使用
为什么要使用Charles:
关于charles使用
ps:在手机上测试本地电脑运行的程序时也需要修改连接的WiFi的http代理:就是上述文章中二3中的步骤;
手机测试时候可以抓包,查看哪一步发生了错误。
Charles 的Map 功能分Map Remote 和Map Local 两种,顾名思义,Map Remote 是将指定的网络请求重定向到另一个网址,Map Local 是将指定的网络请求重定向到本地文件。
正向代理和反向代理区别
Nginx(三)------nginx 反向代理
简单讲:
正向代理:代理的是客户端,客户端知道请求发送的目的地是一个代理,服务端永远不知道真正的客户端是谁。
反向代理:代理的是服务端,客户端不知道发送的目的地其实是一个代理,它永远不知道真正的服务端是谁。
Windows10无法修改host问题
Q:win10安全性过高
A:C:\Windows\System32\drivers\etc\hosts修改属性-安全–选择用户名-勾选可写-确定
为什么要修改host?
简单讲就是加快DNS查找,或者说是“更改”DNS查找的IP地址,
react-redux使用问题
关于高阶组件
dva框架就是集成了react-redux redux-saga等框架,我们都知道connect是一个高阶组件(就是一个函数),传入一个UI组件,connect会给它注入props,
一个问题:我向一个使用了connect的组件里面传递了额外props,动态修改props,希望能引起高阶组件返回的组件的重新渲染,事实上是不可行的:
经过多方搜索后发现这种问题属于动态引用高阶组件,改变方案把数据存进store中,仍然不能动态更新,最后定位问题:
react-redux中高阶组件connect的mapStateToProps不持续更新的问题
connect中只有state的引用对象发生改变时才会更新props
可以发现在models文件夹下:reduers同步修改state的时候也是采用扩展运算符加新值覆盖的方式即return新的对象来修改state。
关于强制刷新 store中值丢失
解决方案:
- 存到sessionStorage
- 根据具体业务逻辑,在单页应用中刷新以后可以toast提示信息失效然后跳转到存store值的页面
rc-form表单
表单(自定义)验证
—结合antd 或者antd-mobile一起使用
本次结合antd-mobile中inputItem中使用:
Form.getFieldDecorator里面的rules可否用自定义方法来进行validate
不管是getFieldProps还是getFieldDecorator都一样:
官方文档中写到getFieldProps Will create props which can be set on a input/InputComponent which support value and onChange interface.
After set, this will create a binding with this input. 主要就是建立了绑定,可以在组件中的任何位置通过form.getFieldsValue()获取到(所有的值)
关于表单校验这部分主要是靠:async-validator 这个对数据进行异步校验的库:而看rc-form的getFieldProp使用时options里面校验规则则是使用了它的校验方式:
Form.getFieldDecorator里面的rules可否用自定义方法来进行validate
上面的文章中囊括了使用常见校验规则以及常见规则无法满足需求时:自定义校验规则
// 最后提交时表单总体验证
// getFieldsError收集所有errors返回对象键值对
validateFields((err, data) => {
if (err) {
console.info(data);
const errs = getFieldsError();
Object.values(errs).every((e) => {
if (e) {
Toast.fail(e[0]);
return false;
}
return true;
});
return;
} if (data.password !== data.reConfirmPwd) {
Toast.fail('两次输入的密码不一致');
return false;
}
const datas = {
...data,
mobile: data.mobile.replace(/\s+/g, ''),
};
this.submitForm(datas);
});
补充点:
Object.values()
方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in
循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
数组不建议用for…in原因:for ... in
循环语句将返回所有可枚举属性,包括非整数类型的名称和继承的那些。因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。
如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames()
或执行 hasOwnProperty()
来确定某属性是否是对象本身的属性(也能使用propertyIsEnumerable
)。或者,如果你知道不会有任何外部代码干扰,您可以使用检查方法扩展内置原型。
- 至于对于every方法的使用:因为必须有返回,所以不能用遍历方法forEach,所以用every最佳(且不能用some)(只有所有校验通过才能提交所有结果);
表单设置初始值
setFieldsValue可以用来直接设置表单初始值;
getFieldsValue可以用来获取表单中的值;
区别于这种向表单注入数据的方式;
我们还可以直接在createForm这个高阶组件中做一步将props映射为Fields的转换:但是注意一定要与createFormField一起使用:但这个在npm中并没有体现。
关于antd表单的双向绑定
使用步骤是抽离Form组件独立出来,父组件给它传props,然后其解构。
mapPropsToFields(props) {
const { initialData } = props;
const fields = {};
Object.keys(initialData).forEach((key) => {
fields[key] = createFormField({
value: initialData[key] || '',
});
});
return fields;
},
这样在使用了getFieldProps或者getFieldDecorator创建了props的组件就可以收到这些初始值;
还可以在createForm里面定义onFieldsChange(Called when field changed, you can dispatch fields to redux store.)当表单发生变化的时候将值存入store;
- 补充:Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可枚举,那么将返回由键组成的数组。(和Object.values()区分)
css样式问题
多字转为…显示:以下四点是必须的:
-
width:xx;/*定宽*/ overflow:hidden; text-overflow:ellipisis; white-space:nowrap; /*不折行*/
文字折行,以下前两点是必须的:
-
width:100px;/*定宽*/ white-space: normal;/*可折行*/ word-wrap: break-word;/*word-wrap 属性允许长单词或 URL 地址换行到下一行。*/ word-break: break-all;/*规定自动换行的处理方法。*/
移动端显示toolTip:
<div className=style.xxx tooltip-context="{item.name}">{item.name}</div>
[tooltip-content]{/*视情况设定*/
position:relative;
}
[tooltip-content]:after{
content:attr(tooltip-content);
position:absolute;
left:0%;
bottom:100%;
visibility:hidden;
max-width:600px;
padding:1px 8px !important;
border-radius:0;
border:1px solid #888 !important;
background:white;
color:#666;
box-shadow:5px 5px 5px -2px #888888;
}
[tooltip-content]:hover:after{
transition-delay:100ms;
visibility:visible;
opacity:1;
}
关键点:
- content 属性与 :before 及 :after 伪元素配合使用,来插入生成内容。
- 伪元素使用:伪元素来消除浮动;插入生成内容:添加icon;
SEO基础知识
- 反链:
反向链接。在SEO优化过程中,它是相对于两个网页来讲的,打个比方,对于网页D来讲,如果某个网页C给网页D做了链接,无论是同一个站还是不同的站,网页C上的这个链接,对于网页D来讲,它都是反链。
- 外链:
SEO优化推广中,经常谈及外链的概念,外链即指外部链接到我们网站的链接。对于一个网站来讲,尤其是新建的网站,外链接入得越多,也就有了越多的入口,蜘蛛越容易爬进我们的网站,我们网站的收录、排名通常越好,当然,这是基于外链质量的基础上。如果外链没有质量,光只有数量,也是不行的
- 友链:
这个可以理解为互换链接的合作关系。你把其他人的网站链接到你的网站,你的网站链接到对方的网站,这是对等交换。
- 作用:
反链,是SEO推广技巧中进行网站内部页面优化必须做的工作。反链可以提高网站权重和排名,在保证反向链接指令的前提下,反链越多,排名相对越好。
外链,对于各大搜索引擎算法,外链是极为重要的判断因素。外链对相关性、收录及权重的影响,直接导致各大网站流量和排名的不同。外链就像一条条道路,可以吸引蜘蛛来抓取网站,作为连接诱饵,来不断的爬行我们的网站,有利于网站的收录速冻和网站快照的更新,有利于SEO关键词排名。当然了,带来流量、用户这些自然不必去细说。
友链,它其实可以理解为一个外链。比如,你跟别人交换了一个友情链接,是不是意味着你从网站之外获得了一个链接入口呢?所以讲,外链的作用,友链都有。能获得好的友链,对自己网站权重、排名都是非常好的。
-
营销漏斗模型:运营管理离不开这个营销漏斗模型,漏斗可以认为是倒金字塔结果,层级分为展示,点击,访问,浏览,咨询,成单,几个层级。逐级递减。
input type=file的一些使用
当然可以用antd-mobile封装好的imagePicker组件,直接按说明文档来写就可以。其封装原理就是基于原生的input标签操作,审查元素可以发现只是input设置为opacity设置为0了。
那么就用原生input来实现一下上传图片反显图片:
使用JS获取当前页面input type=file 的真实路径
主要处理的问题包括:
-
浏览器兼容问题:
- 使用window.URL.createObjectURL会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。将其赋值给img标签的src即可做到可以预览图片的功能。
-
event.target使用:触发该事件的dom节点(怎么感觉用它比this更安心呢,也省去了使用ref操作dom节点的麻烦)
-
e.target.files返回的是FilesList一个==类数组(不是数组)==对象:files,上传一张图片长度就是1,多张就是n
-
另外一些开发中经常遇到的问题
- 样式问题:建议重新定义宽度(block一下),样式
- 上传同一个文件,不会触发onChange–>上传结束后将input的value置为null
event.target和this区别(主要就是this会变,但是event.target不会变)
import React, {Component} from 'react';
import style from './input.less'
export default class Input extends Component {
constructor(props) {
super(props);
this.state = {
src:'',
};
}
_getObjectURL(file) {
var url = null;
if (window.createObjcectURL != undefined) {
url = window.createOjcectURL(file);
} else if (window.URL != undefined) {
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) {
url = window.webkitURL.createObjectURL(file);
}
return url;
}
handleImageChange=(e)=>{
//target 事件属性可返回事件的目标节点(触发该事件的节点)
const file=e.target.files[0];
console.info(file);
const URL = window.webkitURL;
// 通过 file 生成目标 url
const imgURL = this._getObjectURL(file);
console.info(imgURL);
this.setState({src:imgURL});
this.input.value=null;
}
// 点击图片删除
handleImgDelete=(e)=>{
console.info(e.target);
this.setState({src:null});
}
render() {
const {src}=this.state;
// console.info(style);
return (
<div className={style['input-com']}>
<input className={style.container} type="file" onChange={this.handleImageChange}
ref={(input)=>this.input=input}/>
<img className={style.img} src={src} alt="上传图片" onClick={this.handleImgDelete}></img>
</div>
)
}
}
flex布局使用
tips
- 注意这里关于子容器–>flex单值的解释是错误的,因为经过测试发现:
设置
flex:20px;/*浏览器显示:flex:1 1 20px;*/
flex:0 0 20px;/*才是只是flex-basis*/
- 父容器属性flex-wrap的应用:
/*flex盒子在必要时候进行拆行,添加reverse则表示为相反方向*/
flex-wrap:wrap-reverse;
======>
- 关于flex:1占用剩余空间
我们知道在布置三栏(无论水平还是垂直),两栏布局的时候都会用到flex:1来占据剩余所有空间。是什么原因呢?
- flex:1就是1 1 0%
- flex-grow 即定义如何去分配父容器的剩余空间 ,当值为0时,则子元素都不会索取父容器的剩余空间,值为1时就是就会和其他设置了flex-grow的元素一同参与按比例瓜分剩余空间。
- flex-shink用来指定父容器空间不够时子元素的缩小比例,默认为1。如果一个 flexbox 项目的 flex-shrink 属性为0,则该元素不会被压缩。
- flex-basis 用来定义子元素的默认宽或高。如果父容器 flex-direction 属性的方向为水平方向则为宽度,如为垂直方向则为高度。相当于给子元素设置宽或高。如果同时设置了该属性的宽或高,则该属性权重大于宽或高的值。
references:
flexbox 剩余空间分配规则
flex
flex属性简写详解可以看看。
获取url参数
关键点:
-
window.location.search得到的是包含?在内的url?后面的参数;
-
使用encodeURIComponent 和decodeURIComponent:encodeURI 和 decodeURI 函数操作的是完整的 URI;这俩函数假定 URI 中的任何保留字符都有特殊意义,所有不会编码它们。
encodeURIComponent 和 decodeURIComponent 函数操作的是组成 URI 的个别组件;这俩函数假定任何保留字符都代表普通文本,所以必须编码它们,所以它们(保留字符)出现在一个完整 URI 的组件里面时不会被解释成保留字符了。
一张图看懂encodeURI、encodeURIComponent、decodeURI、decodeURIComponent的区别
const getLocationParams = (_location = window.location) => {
let { search } = _location;
if (search.length > 1) {
const params = {};
search = search.substring(1);
search.split('&').forEach((item) => {
const tempParam = item.split('=');
params[tempParam[0]] =
tempParam[1] === '' ? null : decodeURIComponent(tempParam[1]);
});
return params;
}
return null;
};
react 中input 的defaultValue和value的区别
主要牵扯到:受控组件和非受控组件的区别;
使用value搭配onchange变成受控组件
使用defaultValue就是非受控组件
起因是:在自己做的demo中,参见github使用defaultValue导致出现删除指定条目时虽然state变了并且map成的props也改变了,但是页面中删除的条目不对:总是删除最后一条。最后定位问题是defaultValue问题,将其改变为value;