本文是Scratch3.0二次开发添加登录功能部分——添加点击登录按钮弹窗功能,下一篇会介绍添加接口部分以及登录接口怎么写。
0. 写在前面
借鉴:http://www.liyblog.top/ 感谢!希望能一直更新。
因为我对react本身不如vue那么熟悉,而且今日来感觉react比vue要繁琐很多,相关资料和帖子也远不如vue多,所以走了些弯路,如今总结一下,过程中可能不是很规范正确,产生一些问题,希望各位评论指出来,
当然如果有更好的办法和帖子麻烦也在评论添加地址,我也去学习一下,总之希望能一起学习成长。我的邮箱:yh709459462@163.com。
1. 基本文件结构
因为是借鉴上边大佬的博客http://www.liyblog.top/p/22,我暂时时间比较紧不做赘述,以后再完善。所以各位有需要的先去按照他的教程,一步步往下走,大致是一样的,但是因为我和另一个人按教程走完后并不能成功,所以我做了一些改动。
整个博文内容较多,有点格式问题请谅解
按照上边的教程,走的差不多了之后,跟着我往下走。我的顺序可能是纯粹的改动,不会根据react运行流程去一个文件跳一个文件的改,这样更快,看上面的博文就能理解了文件跳转了。改动主要如下:
(1)componets/login-modals目录以及里面的login-modals.jsx更改名字为login。其他文件不用动。
login.jsx文件:
import Modal from '../../containers/modal.jsx';
import styles from './login.css';
import React from 'react';
import PropTypes from 'prop-types';
import Box from '../box/box.jsx';
import SubmitLoginButton from './submit-login-button.jsx';
import SubmitSetupButton from './submit-setup-button.jsx';
// eslint-disable-next-line no-unused-vars
import connect from 'react-redux/es/connect/connect';
import {closeLoginModal} from '../../reducers/modals';
import classnames from 'classnames';
const inputBox = styles.inputBox;
const inputPhone = styles.inputPhone;
const inputPwd = styles.inputPwd;
const Login = props => (
<Modal
className={styles.modalContent}
contentLabel={props.title}
id="loginModal"
onRequestClose={props.onCancel}
>
<Box
className={styles.boxPadding}
>
<div
className={classnames({
[`${inputBox}`]: true,
[`${inputPhone}`]: true
})}
>
<input
className={styles.minInput}
name="account"
placeholder="请输入手机号"
type="text"
/>
</div><br />
<div
className={classnames({
[`${inputBox}`]: true,
[`${inputPwd}`]: true
})}
>
<input
className={styles.minInput}
name="password"
placeholder="请输入密码"
type="password"
/>
</div><br />
<SubmitLoginButton className={styles.btnSubmit} />
<SubmitSetupButton className={styles.setupSubmit} />
</Box>
</Modal>
);
Login.propTypes = {
// eslint-disable-next-line react/no-unused-prop-types
onCancel: PropTypes.func.isRequired,
title: PropTypes.string.isRequired
};
const mapStateToProps = states => ({
loginError: states.scratchGui.userState.error
})
const mapDispatchToProps = dispatch => ({
onCancel: () => dispatch(closeLoginModal())
})
// export default Login;
export default connect(
mapStateToProps,
mapDispatchToProps
)(Login);
注意里面新添的注册按钮
<SubmitSetupButton className={styles.setupSubmit} />按照submit-login-button.jsx复制改个名字就可以了。
(2)修改containers/login.jsx
// eslint-disable-next-line no-unused-vars
import bindAll from 'lodash.bindall'; // 通用绑定this
import PropTypes from 'prop-types'; // 类型
import React from 'react';
// eslint-disable-next-line no-unused-vars
import {injectIntl, intlShape, defineMessages} from 'react-intl'; // 国际化
import BbsComponent from '../components/bbs/bbs.jsx'; // 直播组件
import {connect} from 'react-redux'; // redux 连接器
import {closebbs} from '../reducers/modals'; // 关闭课程弹窗
class Login extends React.PureComponent {
constructor (props) {
super(props);
this.state = {
loading: false // 加载状态
};
}
// eslint-disable-next-line react/sort-comp
render () {
if (!this.props.visible) return null;
return (
<BbsComponent
onRequestClose={this.props.onRequestClose}
loading={this.state.loading}
/>
);
}
componentDidMount (){
}
}
Login.propTypes = {
onRequestClose: PropTypes.func,
visible: PropTypes.bool
};
const mapStateToProps = state => ({
visible: state.scratchGui.modals.bbs
});
const mapDispatchToProps = dispatch => ({
onRequestClose: () => dispatch(closebbs()) // 关闭当前弹窗
});
export default injectIntl(connect(
mapStateToProps,
mapDispatchToProps
)(Login));
(3)修改containers/gui.jsx
showLoginModal: state.scratchGui.modals.login
(4)修改reducers/modals.js中定义相关state:
const MODAL_LOGIN = 'login';
(5)修改components/menu-bar.jsx:
这里是主要修改的部分之一
因为登录按钮是在menu-bar中,这里可以去上边的博文地址查找添加登录入口的博文,我有时间会添加。我直接将按钮的点击事件添加在menu-bar。
37行左右:
import {openTipsLibrary, openLoginModal, closeLoginModal} from '../../reducers/modals';
import LoginButton from './login-button.jsx';
62行左右:
openLoginMenu,
closeLoginMenu,
696行左右(也就是返回的html代码底部):
(
<LoginButton
className={styles.menuBarButton}
onClick={this.props.onClickloginon}
/>
)
769行左右:
onClickloginon: PropTypes.func,
onCancel: PropTypes.func.isRequired
820行左右:
onClickloginon: () => dispatch(openLoginModal()),
onCancel: () => dispatch(closeLoginModal())
至此就基本可以点击登录按钮弹出窗口了。
(6)修改窗口的外观:
modal.css中第19行的: modal-content 是整个弹出框
可以自己修改样式,我是添加了背景图
background-image: url('./loginbg.png') ;
background-position: 0 1.5rem;
其他的样式通过浏览器自行定位,找不到css类名其实可以这么判断
浏览器定位后,确定div的 class,是.modal_modal-content_3brCX ,这里直接取 modal-content 即可,.login_input-phone_3BEMD,取
input-phone即可找到
_和- 两个符号 的规律自己体会。
下面放上我components/login目录结构和css
login.css:
@import "../../css/colors.css";
@import "../../css/units.css";
.modal-content {
560px;
background-repeat:no-repeat;
background-size:100% 100%;
-moz-background-size:100% 100%;
}
.box-padding {
22rem;
height: 100%;
float: right;
padding: 2rem 2rem 3rem 6rem;
/*padding: 40px 40px 40px 230px;*/
}
.input-box{
background-repeat: no-repeat;
background-position: .3rem center;
border-bottom: 1px solid #eaeaea;
margin-bottom: 1rem;
height: 2.2rem;
padding-left: 2rem;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
background-size: auto 1rem;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
}
.input-phone{
background-image: url("./phone.png");
}
.input-pwd{
background-image: url("./pwd.png");
}
.min-input, .max-input {
border: none;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
height: 1.5rem;
border-left: 1px solid #f7f7f7;
outline: none;
text-indent: 1rem;
font-size: .8rem;
-webkit-transition: all .3s;
-o-transition: all .3s;
transition: all .3s;
}
.submit-login-button {
background: $data-primary;
}
.btn-submit {
background: linear-gradient(90deg,rgba(51,200,255,1),rgba(112,146,255,1));
font-size: 1.1rem;
box-shadow: 0 8px 7px 0 rgba(112,146,255,0.22);
border-radius: 1.2rem;
letter-spacing: .5rem;
/*background: hsla(40, 100%, 55%, 1);*/
height: 2.4rem;
alignment: center;
cursor: pointer;
font-weight: bold;
display: grid;
flex-direction: row;
align-items: center;
user-select: none;
color:#fff;
text-align: center;
}
.setup-submit{
text-align: center;
color: #999;
font-size: .7rem;
text-decoration: none;
line-height: 1.5em;
display: block;
padding: 1rem 0;
}
.login-Btn{
display: grid;
text-align: center;
}
.setup-Btn{
display: grid;
text-align: center;
}
modal.css:
@import "../../css/colors.css";
@import "../../css/units.css";
@import "../../css/z-index.css";
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: $z-index-modal;
background-color: $ui-modal-overlay2;
}
.modal-content * {
box-sizing: border-box;
}
.modal-content {
margin: 100px auto;
outline: none;
border: 4px solid $ui-white-transparent;
padding: 0;
border-radius: $space;
user-select: none;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: $text-primary;
overflow: hidden;
background-image: url('./loginbg.png') ;
background-position: 0 1.5rem;
}
.modal-content.full-screen {
position: absolute;
display: flex;
height: 100%;
100%;
overflow-y: auto;
-webkit-overflow-scrolling: 'touch';
user-select: none;
background-color: $ui-secondary;
/* Default modal resets */
margin: 0;
border: none;
border-radius: 0;
}
/*
Modal header has 3 items:
|filter title x|
Use the same width for both side item containers,
so that title remains centered
*/
$sides: 20rem;
.header {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
height: $library-header-height;
box-sizing: border-box;
100%;
background-color: $motion-primary;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 1rem;
font-weight: normal;
}
.header-item {
display: flex;
align-items: center;
padding: 1rem;
text-decoration: none;
color: $ui-white;
user-select: none;
}
[dir="ltr"] .header-image {
margin-right: 0.5rem;
}
[dir="rtl"] .header-image {
margin-left: 0.5rem;
}
.header-item-filter {
display: flex;
flex-basis: $sides;
justify-content: flex-start;
}
.header-item-title {
flex-grow: 1;
flex-shrink: 0;
justify-content: center;
user-select: none;
letter-spacing: 0.4px;
cursor: default;
}
[dir="ltr"] .header-item-title {
margin: 0 -$sides 0 0;
}
[dir="rtl"] .header-item-title {
margin: 0 0 0 -$sides;
}
.full-screen [dir="ltr"] .header-item-title {
margin: 0 0 0 -$sides;
}
.full-screen [dir="rtl"] .header-item-title {
margin: 0 -$sides 0 0;
}
.header-item-close {
flex-basis: $sides;
justify-content: flex-end;
z-index: 1;
}
.full-screen .header-item-close {
order: -1;
justify-content: flex-start;
}
.back-button {
font-weight: normal;
padding-right: 0;
padding-left: 0;
}
[dir="rtl"] .back-button img {
transform: scaleX(-1);
}
.header-item-help {
padding: 0;
z-index: 1;
}
[dir="ltr"] .header-item-help {
margin-right: -4.75rem;
}
[dir="rtl"] .header-item-help {
margin-left: -4.75rem;
}
.help-button {
font-weight: normal;
font-size: 0.75rem;
}
[dir="ltr"] .help-button {
padding-right: 0;
}
[dir="rtl"] .help-button {
padding-left: 0;
}
3. 写在最后
感谢http://www.liyblog.top的博文给我带来的帮助
有问题可以评论或者发我邮箱yh709459462@163.com 数字部分是我q,着急的时候再加,注明来意,请勿骚扰。