react中的e和event

react中获取元素事件触发的DOM对象,我们可以通过e.target和event.target来获取,但是用的时候需要注意一下

  1. 在调用的事件方法中不需要传参,但是在方法声明的时候需要放入event,并放在最后一个参数的位置,示例
1
2
3
4
handleChange(item,event) {
this.setState({value: event.target.value});
}
<input type="text" value={this.state.value} onChange={this.handleChange.bind(this,item)} />
  1. 而e和event是一样的,只是e是event的简写
    1
    2
    3
    4
    handleChange(item,e) {
    this.setState({value: e.target.value});
    }
    <input type="text" value={this.state.value} onChange={this.handleChange.bind(this,item)} />

再谈iphonex适配问题

写在前面:近日处理线上项目里iphonex的适配问题,本以为自己之前处理过相应的问题,那本次处理也会得心应手,速度杠杠的改完。结果并不是,不得不说iphonex的适配问题真心让前端处理起来就像处理ie6一样难受。但是经过多次的趟水,摸到门道,总结下来,就不会害怕下次的问题到来。

处理适配问题,按照以下几个注意点处理就行

1.name为viewport的meta标签中的设置,content中设置viewport-fit=cover

1
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, viewport-fit=cover" name="viewport" />

2.给body设置安全区域,请将env设置加上,貌似现在constant对最新版本的ios系统根本不生效。

1
2
3
4
5
6
body {
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}

3.如果在页面顶部有position为fixed或者absolute,请设置top为0的同时,要加上下面的样式

1
2
3
4
5
.header {
top: 0;
top: constant(safe-area-inset-top);
top: env(safe-area-inset-top);
}

4.如果在页面顶部有position为fixed或者absolute,但是你的top不为0,请不要用网络上所说的计算calm来写,因为要么就是不能生效,要么就是生效了,但是结果不是你想要的。用margin来处理你需要空出的安全距离,示例如下

1
2
3
4
5
.header {
top: .2rem;
margin-top: constant(safe-area-inset-top);
margin-top: env(safe-area-inset-top);
}

5.其他地方的处理是一个道理

react项目中引入了redux后js控制路由跳转方案

如果你的项目中并没有用到redux,那本文你可以忽略

问题引入

纯粹的单页面react应用中,通过this.props.history.push(‘/list’)就可以进行路由跳转,但是加上了redux后,使用这个语句并不能生效。相信你在做的过程也遇到了此问题,控制台报错了-_-

1
Uncaught TypeError: Cannot read property 'push' of undefined

解决方案

  1. 在将要使用js控制路由的组件中引入withRouter方法;

    1
    import { withRouter} from 'react-router-dom';
  2. 导出类的时候运用该方法

    1
    export default withRouter(MailListLeft)
  3. 在MailListLeft组件中正常使用 this.props.history.push(‘/list’)

    1
    <button type="button" onClick={()=>{this.props.history.push("/list");}}>去列表页面</button>

Vue获取插槽slot元素的宽度和高度

碰到问题后尝试的解决方案

当我们在写Vue组件的时候,组件内有不确定模块,通常会放置插槽slot来完成,但是组件内还需要获取插槽的宽度和高度来完成该组件的功能,那么本人就在这个获取宽度和高度的时候折腾了一点时间。我一开始尝试的办法有两种,最后均以失败告终。

  1. 尝试方法一:
    将插槽外面包一个div,然后给该div赋值refs属性,通过this.$refs.element.offsetHeight和this.$refs.element.offsetWidth来获取。
  • 模板部分
1
2
3
4

<div refs="element">
<slot name="slideoper"></slot>
</div>
  • js部分
1
2
3
4
5
6
7

mounted () {
let left = this;
left.$nextTick(() => {
left.buttonWidth = self.$refs.element.offsetWidth;
})
}
  1. 尝试方法二:
    将插槽外面包一个div,然后给div赋值id,通过this.$el.querySelector(‘#element).offsetWidth
  • 模板部分
1
2
3
4

<div id="element">
<slot name="slideoper"></slot>
</div>
  • js部分
1
2
3
4
5
6
7

mounted () {
let left = this;
left.$nextTick(() => {
left.buttonWidth = self.$el.querySelector('#element').offsetWidth
})
}

以上两种方式并没有解决问题,后来在钩子中mounted打印了一下this,发现它有元素$slots就可以获取到卡槽的所有内容,以下附上最终的解决方案。

  • 模板部分
1
<slot name="slideoper"></slot>
  • js部分
    1
    2
    3
    4
    5
    6
    7
    8
    mounted () {
    let left = this;
    left.$nextTick(() => {
    for(var slot of left.$slots.slideoper) {
    left.buttonWidth = left.buttonWidth + slot.elm.offsetWidth;
    }
    })
    }

感受:只有在不断的实践和填坑中才能get到更多!

react中input的defaultValue和value属性

问题引入

以下是官方文档介绍受控表单组件

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
export default class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
mobile: '',
addressDetail: ''
}
}
handleInputChange(event) {
let self = this;
let target = event.target;
let name = target.name;
self.setState({
[name]: target.value
});
if(self.props.onUpdate) self.props.onUpdate(self.state);
}
render() {
let self = this;
return (
<div className="form-input">
<div className="input-item">
<div className="input-label">收货人</div>
<div className="input-con">
<div className="input-wrap"><input className="txt-input" type="text" name="name" value={self.state.name} onChange={self.handleInputChange.bind(self)}/><i className="i-del"></i></div>
</div>
</div>
<div className="input-item">
<div className="input-label">手机号码</div>
<div className="input-con">
<input className="txt-input" type="text" value={self.state.mobile} name="mobile" onChange={self.handleInputChange.bind(self)}/>
</div>
</div>
<div className="input-item">
<div className="input-label">所在区域</div>
<div className="input-con">
<input className="txt-input" type="text" value={self.props.pcat}/>
<a href="javascript:void(0)" className="sel-addr" onClick={this.props.onInputArea.bind(this)}></a>
</div>
</div>
<div className="input-item">
<div className="input-label">详细地址</div>
<div className="input-con">
<textarea className="txt-textarea" value={self.state.addressDetail} name="addressDetail" onChange={self.handleInputChange.bind(self)}></textarea>
</div>
</div>
</div>
);
}
}

按照以上写法可以完成简单的表单输入,并提交数据,但是现在需要先给表单填上从父组件传过来的props的初始数据,马上想到defaultVaule对不对?思路是对的,但是当我修改成如下代码之后,视图并没有像我们意料中一样展示出来。

1
<input className="txt-input" type="text" defaultValue={self.props.editAddress.name} value={self.state.name} name="name" onChange={self.handleInputChange.bind(self)}/>

编译后的html如下,value里依然是空的,这并不是我想要的

1
<input type="text" class="txt-input" value="" name="name">

解决方案

实际上我被defaultValue带偏了,value里不是已经给了state吗?并且state就有默认值为空,所以在这里设置defaultValue并没有什么卵用。

value默认值就是props,那直接给value赋值props不就好了。

1
<input className="txt-input" type="text" value={self.props.editAddress.name} name="name" onChange={self.handleInputChange.bind(self)}/>

这样修改后,onChange事件就需要通过修改父组件的state值,来修改当前输入组件的value中props的值,如下更改:

  • 子组件
1
<input className="txt-input" type="text" value={self.props.editAddress.name} name="name" onChange={self.props.onUpdate.bind(self)}/>
  • 父组件
    1
    <Form onUpdate={self.updateAddress.bind(self)} pcat={self.state.pcat} onInputArea={self.openArea.bind(self)} editAddress={self.state.submitParams}/>

如上修改完成后,功能实现没问题了,但是控制台此时给了你一个警告,告诉你:

1
Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components

警告大致意思就是说你现在是受控组件,但是这个组件是不需要受控的。所以你需要改成非受控组件,那么去看看官方非受控组件是咋写的,然后回来改改。改完如下:

  • 子组件
1
<input className="txt-input" type="text" value={self.props.editAddress.name||''} name="name" onChange={self.props.onUpdate.bind(self)}/>

windows环境用jekyll搭建博客详细步骤

window环境准备

  1. rubyinstaller 下载及安装 rubyinstaller下载页 记得全部勾选
  2. Ruby DevKit 下载devkit压缩包 devkit下载页 解压该压缩包,进入到该目录
  3. 解压该DevKit压缩包,用命令行(cmd)进入到该目录,如:cd /e:/devit
  4. 执行ruby dk.rb init 会看到找到ruby的安装目录,如果看不到请手动修改该目录下confit.yml的ruby安装目录,注意格式 - D:\Ruby23-x64,带有横线
  5. 执行ruby dk.rb install
  6. 执行gem install jekyll 用jekyll -v检测是否安装成功

用jekyll初始化项目并在本地预览

  1. jekyll new blog 初始化一个jekyll项目
  2. bundler install 安装依赖包
  3. bundler update 更新依赖包,选做步骤
  4. jekyll serve启动项目 去http://127.0.0.1:4000访问

将项目部署到github

  1. 新建仓库,名字要与自己的用户名相同
  2. 创建完成后,克隆下来到本地
  3. 把本地用jekyll初始化的项目放入克隆的项目中
  4. 提交项目至master分支

效果预览

主题,gemfile和_config.yml里的俩主题要对应(todo)

jekyll相关命令

  • jekyll serve 或者bundle exec jekyll serve 启动项目命令
  • gem unistall jekyll 卸载jekyll
  • gem install jekyll -v 3.1.6

相关资料