**写在前面**
该系列文章是为具有开发能力的朋友写作的,目的是帮助他们在scratch 3.0的基础上开发一套完整的集scratch 3.0编程工具、用户社区和作品云端存储及分享、品牌集成于一体的scratch编程平台。如果您不是开发者,但想要拥有自己的教育平台和品牌,也欢迎学习交流和洽谈合作。
所以如果您是想学习scratch少儿编程课程,那请忽略该系列的文章。
**前言**
我们继续之前的集成后台用户系统的工作。
这一章我们将增加登录界面,在用户点击登录按钮时,弹出一个登录窗口,用户输入用户名密码,如果登录成功,回到主界面并且在右上角的menu-bar展示用户信息。
**开始实现**
先来实现登录的弹窗组件。
我们发现scratch-gui中已经定义了自己的ModalCompoent组件和container Modal。这样最好。我们可以在这个modal基础上来完成我们的登录弹窗组件,从而保持与已有的风格样式一致。
在components中新建login-modal文件夹,并在里面创建login-modal.jsx文件,我们来在login-modal.jsx中实现登录组件的样式,包括一个弹窗,两个输入框和一个提交按钮。
定义LoginModal的基本结构:
>
>
> ~~~
> import Modal from '../../containers/modal.jsx';
> import styles from './login-modal.css';
> import React from 'react';
> import PropTypes from 'prop-types';
> import Box from '../box/box.jsx';
> import SubmitLoginButton from './submit-login-button.jsx';
> import connect from 'react-redux/es/connect/connect';
> const LoginModal = props => (
> <Modal
> className={styles.modalContent}
> contentLabel={props.title}
> id="loginModal"
> >
> <Box>
> <input
> className={styles.minInput}
> name="account"
> placeholder="账号"
> type="text"
> /><br />
> <input
> className={styles.minInput}
> name="password"
> placeholder="密码"
> type="password"
> /><br />
> <SubmitLoginButton className={styles.btnSubmit} />
> </Box>
> </Modal>
> );
> LoginModal.propTypes = {
> title: PropTypes.string.isRequired
> }
> export default LoginModal;
> ~~~
>
>
其中包括一个提交登录的按钮组件SubmitLoginButton,实现于submit-login-button.jsx中:
>
>
> ~~~
> import classNames from 'classnames';
> import {FormattedMessage} from 'react-intl';
> import PropTypes from 'prop-types';
> import React from 'react';
> import Button from '../button/button.jsx';
> import styles from './login-modal.css';
> const SubmitLoginButton = ({
> className,
> onClick
> }) => (
> <div>
> <Button
> className={classNames(
> className,
> styles.SubmitLoginButton
> )}
> onClick={onClick}
> >
> <FormattedMessage
> defaultMessage="登录"
> description="Label for submit login"
> id="gui.loginModal.submitLogin"
> />
> </Button>
> </div>
> );
> SubmitLoginButton.propTypes = {
> className: PropTypes.string,
> onClick: PropTypes.func
> };
> SubmitLoginButton.defaultProps = {
> onClick: () => {}
> };
> export default SubmitLoginButton;
> ~~~
>
>
login-modal.css中样式内容:
>
>
> ~~~
> @import "../../css/colors.css";
> @import "../../css/units.css";
> .modal-content {
> width: 360px;
> }
> .min-input, .max-input {
> margin-bottom: 1.5rem;
> width: 100%;
> border: 1px solid $ui-black-transparent;
> border-radius: 5px;
> padding: 0 1rem;
> height: 3rem;
> color: $text-primary-transparent;
> font-size: .875rem;
> }
> .submit-login-button {
> background: $data-primary;
> }
> .btn-submit {
> background: hsla(30, 100%, 55%, 1);
> height: 2rem;
> alignment: center;
> cursor: pointer;
> border-radius: $form-radius;
> font-weight: bold;
> display: flex;
> flex-direction: row;
> align-items: center;
> padding-left: 9.75rem;
> user-select: none;
> }
> ~~~
>
>
我们尽量复用已有组件的样式,从而保持整体风格一致。
现在我们可以先在gui.jsx组件里使用一下,看一下当前的效果,将它写到gui.jsx的组件中:
![](https://img-blog.csdnimg.cn/202002141607551.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
编译运行:
![](https://img-blog.csdnimg.cn/20200214160901971.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
看到确实出现了登录弹窗界面。
好了。刚才为了调试样式,我们在components/gui.jsx中写死了显示LoginModal,现在我们需要在Login被点击时显示它,点击右上角的X时关闭它。
为了实现LoginModal在GUIComponent中的显示,我们需要先为GUIComponent添加一个属性showLoginModal,通过它的值来判断是否展示。
![](https://img-blog.csdnimg.cn/2020021416164134.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
components/gui/gui.jsx:
![](https://img-blog.csdnimg.cn/20200214161817601.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
然后修改containers/gui.jsx,将showLoginModal的值与state映射起来:
![](https://img-blog.csdnimg.cn/20200214162449553.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
这里我们将props showLoginModal的值映射给:
> state.scratchGui.modals.loginModal
所以我们需要去reducers/modals.js中定义相关state:
![](https://img-blog.csdnimg.cn/2020021416292939.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
定义打开和关闭的actions:
![](https://img-blog.csdnimg.cn/20200214163349405.png)
![](https://img-blog.csdnimg.cn/20200214163405497.png)
最后记得将它们export:
![](https://img-blog.csdnimg.cn/20200214163639713.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
现在回到components/menu-bar/login-button.jsx,将它的onClick方法映射到openLoginModal中:
![](https://img-blog.csdnimg.cn/20200214164014438.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
这样点击菜单栏的Login按钮,将会打开LoginModal。
然后是components/login-modal/login-modal.jsx,为它添加关闭登录窗的处理:
![](https://img-blog.csdnimg.cn/2020021416470236.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200214164842689.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
好了,重新编译运行,我们发现登录弹窗和关闭弹窗就实现完成了:
![](https://img-blog.csdnimg.cn/20200214164937721.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RhbmtfZnQ=,size_16,color_FFFFFF,t_70)
先到这里吧,下一章我们将对接登录接口,完成登录获取用户信息并在右上角展示的功能。