🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
**写在前面** 该系列文章是为具有开发能力的朋友写作的,目的是帮助他们在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) 先到这里吧,下一章我们将对接登录接口,完成登录获取用户信息并在右上角展示的功能。