开启两个react app时,显示Something is already running on port 3000.
解决:PORT=3001 npm start
Import相对路径引用
‘./同一文件夹内文件’
‘../父级文件夹兄弟文件’npm i 依赖安装 报错 error -4058 syscall access
解决:使用cnpm i报错Each child in an array or iterator should have a unique “key” prop.
原代码1
2
3const imgList = imgStr.map((image) =>
<li className="icon-wrap"><img src={image} alt=""/></li>react
);修改后
1
2
3const imgList = imgStr.map((image,i) =>
<li className="icon-wrap" key={i}><img src={image} alt=""/></li>
);同一行文字图片不对齐
解决: 给文字设置vertical-align: top;
属性。‘props’ is not defined
解决:props调用前需要加this,{this.props.image}
。修改state数组中某一个
1
2
3
4
5
6
7
8
9
10
11constructor(props) {
super(props);
this.state = {open: [false,false,false,false,false,false,false,false,false,false]};
this.handleClick = this.handleClick.bind(this);
}
handleClick(i) {
let state = this.state;
state[i] = !state[i];
this.setState({state: state})
}Map事件绑定
需要先将map变量保存在变量中再输出。为什么?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17render() {
let wideList = listStr.map((it, i) =>
<li className="list-wrap" key={i} >
<div className="big-list"
onClick={this.handleClick.bind(this, i)}>
<img src={it.image} alt=""/>
<span>{it.name}</span>
</div>
</li>
return (
<div className="wider-sidebar">
<ul>
{wideList}
</ul>
</div>
);
}子组件向父组件传递数据
父:父组件传递带参函数,参数为子组件需要向父组件传递的参数1
2
3
4
5
6
7
8
9
10typeChange(i, typeStr){
let newType = this.state.type;
newType[i] = typeStr;
this.state = {
type: newType
};
}
<SelectBox typeChange={this.typeChange.bind(this)}/>或者
<SelectBox typeChange={(i, typeStr) => this.typeChange(i, typeStr)
}/>
子:子组件调用父组件函数,传入需要传递的参数1
2
3
4
5
6
7handleChange(i, e){
this.props.typeChange(i, this.state.type[i]);//调用父组件函数
}
<input type="text"
list={'type' + (index+1)}
value={this.state.type[index]}
onChange={this.handleChange.bind(this,index)}/>
Js函数全角改半角
1
2
3
4
5
6
7
8
9
10
11
12
13changeMark(str){
let tmp = "";
for(let i=0;i<str.length;i++){
if(str.charCodeAt(i) >= 65281 && str.charCodeAt(i) <= 65374){// 如果位于全角!到全角~区间内
tmp += String.fromCharCode(str.charCodeAt(i)-65248)
}else if(str.charCodeAt(i) === 12288){//全角空格的值,它没有遵从与ASCII的相对偏移,必须单独处理
tmp += ' ';
}else{// 不处理全角空格,全角!到全角~区间外的字符
tmp += str[i];
}
}
return tmp;
}按符号分割字符串。
开始想着是用split,但是split会把标点符号给删了,不行。
解决1. 用match
找到与句子匹配的正则str.match(reg);
直接分割,但是正则表达式没有找着,后续学习。。
解决2. 函数exec1
2
3
4
5let lastindex = 0;
while((r=reg.exec(articleStr))!==null){
sentenceArr.push(articleStr.substring(lastindex, r.index+1));
lastindex=reg.lastIndex;
}Constructor中的super什么意思?
React单选框组件
1
2
3
4
5
6<input type="radio" name="rightAnswer"
value={this.state.value}
checked={this.state.rightAnswer === this.state.value}
onClick={this.rightAnswerChange.bind(this, index)}
onChange={this.rightAnswerChange.bind(this, index)}/>
<label>正确答案</label>Axios执行post请求时,后来获取不到数据,提示Required XXX parameter XXX is not present.
先前写法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19let data={
sentence_contents: sentenceArr,
lesson_type_id: 1,
owner_id: 1
};
axios.post('https://pay.regiondavid.xyz/Qidian-test/lessonEdit/init_sentences', data,{
headers: {
/* 一些公用的 header */
'X-Requested-With': 'XMLHttpRequest'
},
crossDomain: true,
withCredentials: true
})
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.log(err);
})
解决: post参数传递要以"userName='n'& phone='13'& email='12'& emailPwd='22'& kindleEmail='asd'"
形式传递
而上面传递的为对象格式
解决方案1:1
2
3
4let data = new URLSearchParams();
data.append("sentence_contents", '[a,a]');
data.append("lesson_type_id", 1);
data.append("owner_id", 1);
解决方案2:封装一个axios实例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import axios from 'axios'
/* 创建一个新的 AXIOS 对象,确保原有的对象不变 */
let axiosWrap = axios.create({
baseURL: 'https://pay.regiondavid.xyz/Qidian-test'/* 服务器的根路径 */,
headers: {
/* 一些公用的 header */
'X-Requested-With': 'XMLHttpRequest',
},
crossDomain: true,
withCredentials: true,
transformRequest:[function (data, header){
/* 自定义请求参数解析方式(如果必要的话)修改传递data格式 */
let ret = '';
for (let it in data) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&';
}
return ret;
}],
export default axiosWrap
调用1
2
3
4
5
6
7
8
9
10
11
12let data={
sentence_contents: sentenceArr,
lesson_type_id: 1,
owner_id: 1
};
axiosWrap.post('/lessonEdit/init_sentences',data)
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.log(err);
})
- React中props传递的数据类型为数组时,子组件讲改传递值作为了state并修改了他,父组件中相应数组也会跟着修改。
父:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Text1Edit extends Component {
constructor(props) {
super(props);
this.state = {
sentenceArr: [‘a’,’b’,’c’]
}
}
render() {
console.log(this.state.sentenceArr);
return (
<div className="text1-edit">
{ this.state.sentenceArr }
</div>
);
}
}
子:1
2
3
4
5
6
7
8
9
10
11
12
13
14class SentenceArea extends Component {
constructor(props) {
super(props);
let sentenceArr = this.props.arr;
sentenceArr.shift();
// console.log(sentenceArr);
this.state = {
title: this.props.arr[0],
sentenceArr: sentenceArr, //句子字符串
// sentences : this.props.arr.substring(1),
firstIndex: NaN,//第一次点击的句子索引
}
}
解决:复杂类型利用=传值传递的均为地址,即所有对象均指向一个地址,修改一个全部都会改变,所以应该在子组件实现深拷贝,即实现数组的一个备份。
Ajax传递复杂对象类型时,如{a:2,b:{a:1,b:2}}时,直接对该data无法编码,需要预先将b对应的对象转为Json字符串,再传递。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16let data = {
sequence: this.state.sequence,
type: this.state.type,
question: this.state.question,
options: this.state.options,
answer: this.state.answer
};
let dataStr = JSON.stringify(data);
axiosWrap.post('/lessonEdit/upload_reading_comprehension', {
reading_comprehension : dataStr,
lesson_id : this.state.lesson_id
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})Ajax更新父组件State时,传入子组件的props转换为state没有更新,
解决:
1.(暴力方法)通过给子组件添加不同的key即可,这样在每次父组件执行render方法的时候,发现key不相同,则会重新加载子组件;1
2
3
4class Par entend React.PureComponent{
render(){
<Son key=Math.random()/> }
}
2.这种方式,由于我们使用的是state,所以每当父组件每次重新传递props时,我们需要重新处理下,将props转换成自己的state,这里就用到了componentWillReceiveProps。在componentWillReceiveProps中this.props为老的props值,需要引用nextProps获取新的props的值。当父组件的的props更新时,子组件的this.props的值也是从render函数开始执行的时候开始更新的,render之前生命周期函数中都是获取不到最新的this.props的,除非用this.props=nextProps进行更新。
关于你提到的不会二次渲染是这样的:每次子组件接收到新的props,都会重新渲染一次,除非你做了处理来阻止(比如使用:shouldComponentUpdate),但是你可以在这次渲染前,根据新的props更新state,更新state也会触发一次重新渲染,但react不会这么傻,所以只会渲染一次,这对应用的性能是有利的。1
2
3
4
5
6
7
8
9
10
11
12
13
14class Child extends Component {
constructor(props) {
super(props);
this.state = {
someThings: props.someThings
};
}
componentWillReceiveProps(nextProps) {
this.setState({someThings: nextProps.someThings});
}
render() {
return <div>{this.state.someThings}</div>
}
}
不用link利用js实现跳转
1
2
3
4
5import {withRouter} from "react-router-dom";
class QuestionEdit extends Component {
this.props.history.push('/Text2Edit');
}
export default withRouter(QuestionEdit);对象属性名通过(.)与([])调用区别
(.)调用时,后面必须为字符串。
([])调用时,中间可以为变量。git过滤文件以及文件夹
1) 在根目录中创建.gitignore.txt文件,或者在需要创建.gitignore文件的文件夹内进入命令行,输入touch .gitignore即可。
2) 在.gitignore文件里输入你要忽略的文件夹及其文件就可以了。
文件夹用bin/表示,文件后缀用*.dll表示.prevState
1
this.setState((prevState)=>({voicePlay: !prevState.voicePlay}))
html5语音控制播放暂停
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15voicePlay(){
let audio=document.getElementById('audio');
if (audio.paused) {
audio.play();
this.setState({voicePlay: '停止'});
}else{
audio.pause();
audio.currentTime = 0;
this.setState({voicePlay: '停止'});
}
}
<button onClick={this.voicePlay.bind(this)}>{this.state.voicePlay}</button>
<audio id='audio'>
<source src={a} type="audio/mpeg"/>
</audio>动态修改state,封装成函数。
1
2
3stateChange(prop, val) {
this.setState({[prop]: val});
}深拷贝
深拷贝对象还有另一个解决方法,在对象中不含有函数的时候,使用JSON解析反解析就可以得到一个深拷贝对象1
JSON.parse(JSON.stringify(obj));