最近需要在项目中的某个页面嵌入“吐个槽”,项目用的是react全家桶。
要求是携带登录状态信息,因此用组件的形式嵌入,过程中遇到了一些坑,在此记录一下。
吐个槽接入文档(官方出品):
https://tucao.qq.com/helper/configLogonState
重点
- 利用form表单传递登录信息,必须保证在提交前form表单拿到正确的登录信息
- iframe必须有name值,form必须有target,且二者保持一致,否则form表单的默认跳转属性会打开新页面或者替换掉当前页面
问题一:
最初直接使用了官方提供的工具包tucao.js,看了一下源码,就自己实现了一下。没想到问题就来了,form表单提交会在iframe页面里打开一个链接,同时也会新开一个标签页打开链接。试了很多种方法,都没能解决,最后改用iframe中嵌入form,再传入登录信息的方式才解决;
问题二:
form表单提交放到了componentDidMount函数中,有时拿不到更新后的state,因此用了一个定时器,保证能够拿到最新的登录信息
全部代码:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import actions from '@/action'
import './index.less'
// 请填写自己公司的产品ID
const productId = 1212
class Feedback extends Component {
constructor(props) {
super(props)
this.state = {
isLoading: false, // 避免重复获取数据
// 吐个槽提供的默认登录信息,三个字段都必填
nickname: 'tucao_test',
avatar: 'https://tucao.qq.com/static/desktop/img/products/def-product-logo.png',
openid: '-1',
}
}
componentDidMount() {
this.props.loadUserInfo()
// 等待setState数据成功后,再进行form表单提交,避免登录信息提交失败
setTimeout(() => {
this.complainForm.submit()
}, 0)
}
// 获取登录信息
componentWillReceiveProps(nextProps) {
if (nextProps.staff && nextProps.staff.id && !this.state.isLoading) {
const { name, avatar, id } = nextProps.staff
this.setState({
isLoading: true,
nickname: name,
avatar: avatar,
openid: id,
})
}
}
render() {
const { userInfo: { data: { staff }}} = this.props
return (<div className="it-complain">
{
staff.id && <iframe
className="complain-iframe"
src={'https://support.qq.com/product/' + productId} // src为指定嵌入的吐个槽页面
name="complain-iframe" // 必须有,为form表单提供target
>
<form
method="post"
action={'https://support.qq.com/product/' + productId}
target="complain-iframe" // target值为iframe标签的name属性,避免action跳转到其他页面
ref={(form) => { this.complainForm = form }}
>
<input type="hidden" name="openid" value={this.state.openid} />
<input type="hidden" name="nickname" value={this.state.nickname} />
<input type="hidden" name="avatar" value={this.state.avatar} />
<button type="submit" />
</form>
</iframe>
}
</div>)
}
}
const mapStateToProps = (state) => ({
userInfo: state.userInfo,
})
const mapDispatchToProps = {
loadUserInfo: actions.loadUserInfo,
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Feedback))
如果有更好的实现方法,欢迎讨论~
网友评论