<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                **寫在前面** 該系列文章是為具有開發能力的朋友寫作的,目的是幫助他們在刮擦3.0的基礎上開發一套完整的集刮擦3.0編程工具,用戶社區和作品云端存儲及分享,品牌集成于一體的刮擦編程平臺。如果您不是開發者,但想要擁有自己的教育平臺和品牌,也歡迎學習交流和洽談合作。 所以如果您是想學習scratch少兒編程課程,那請忽略該系列的文章。 **前言** 前面我們將scratch-gui工程成功建造運行起來,并且成功植入了我們的品牌徽標,這讓我們對整個項目有了初步的認識。 現在我們已經有了scratch編程工具,但是我們還剩下兩個主要的后臺,用戶社區后臺和GUI的存儲后臺。目前Scratch3.0團隊還沒有發現社區替換和GUI的存儲部分是否有開源計劃,考慮到Scratch2.0的重新初始化開源,3.0社區初始化開源的可能也不大。 scratch-www項目提供了用戶社區的功能,但是需要通過接口去分析它的后臺的數據存儲的結構,我覺得比較麻煩,不如我們自己來開發一個,集成到我們的編程工具scratch-gui中。 所以接下來我們的工作是自己來提供相關的兩個前提平臺,并與GUI集成到一起。 **約會用戶登錄狀態** 我們先一步一步來,先做一個比較簡單的用戶系統,再一步一步迭代。 這一章,我們先來改造一下前面的scratch-gui,約會用戶登錄狀態的檢測。 在進入項目時,檢測用戶是否登錄,如果用戶未登錄,則在右上角顯示登錄按鈕,否則顯示用戶頭像和姓名等基本信息。 先在減少器目錄中創建user-state.js文件,用作記錄用戶的信息。 添加如下內容: > import keyMirror from 'keymirror'; > > const UserState = keyMirror({ > > ? ? NOT\_LOGINED: null, > > ? ? LOGINED: null > > }); > > const UserStates = Object.keys(UserState) > > const initialState = { > > ? ? error: null, > > ? ? userData: null, > > ? ? loginState: UserState.NOT\_LOGINED > > }; > > const getIsLogined = loginState => ( > > ? ? loginState === UserState.LOGINED > > ); > > const reducer = function (state, action) { > > ? ? if (typeof state === 'undefined') state = initialState; > > } 在減少器/gui.js中,作為項目的用戶相關的初始化信息。 在reducer / gui.js中日期用戶狀態: > ??? > > ~~~ > import userStateReducer, {userStateInitialState} from './user-state'; > ``` > 加入到initialState中: > ``` > const guiInitialState = { > ? ? alerts: alertsInitialState, > ? ? assetDrag: assetDragInitialState, > ? ? blockDrag: blockDragInitialState, > ? ? cards: cardsInitialState, > ? ? colorPicker: colorPickerInitialState, > ? ? connectionModal: connectionModalInitialState, > ? ? customProcedures: customProceduresInitialState, > ? ? editorTab: editorTabInitialState, > ? ? mode: modeInitialState, > ? ? hoveredTarget: hoveredTargetInitialState, > ? ? stageSize: stageSizeInitialState, > ? ? menus: menuInitialState, > ? ? micIndicator: micIndicatorInitialState, > ? ? modals: modalsInitialState, > ? ? monitors: monitorsInitialState, > ? ? monitorLayout: monitorLayoutInitialState, > ? ? projectChanged: projectChangedInitialState, > ? ? projectState: projectStateInitialState, > ? ? projectTitle: projectTitleInitialState, > ? ? fontsLoaded: fontsLoadedInitialState, > ? ? restoreDeletion: restoreDeletionInitialState, > ? ? targets: targetsInitialState, > ? ? timeout: timeoutInitialState, > ? ? toolbox: toolboxInitialState, > ? ? vm: vmInitialState, > ? ? vmStatus: vmStatusInitialState, > ? ? userState: userStateInitialState > }; > ``` > 將reducer加入到guiReducer中: > ``` > const guiReducer = combineReducers({ > ? ? alerts: alertsReducer, > ? ? assetDrag: assetDragReducer, > ? ? blockDrag: blockDragReducer, > ? ? cards: cardsReducer, > ? ? colorPicker: colorPickerReducer, > ? ? connectionModal: connectionModalReducer, > ? ? customProcedures: customProceduresReducer, > ? ? editorTab: editorTabReducer, > ? ? mode: modeReducer, > ? ? hoveredTarget: hoveredTargetReducer, > ? ? stageSize: stageSizeReducer, > ? ? menus: menuReducer, > ? ? micIndicator: micIndicatorReducer, > ? ? modals: modalReducer, > ? ? monitors: monitorReducer, > ? ? monitorLayout: monitorLayoutReducer, > ? ? projectChanged: projectChangedReducer, > ? ? projectState: projectStateReducer, > ? ? projectTitle: projectTitleReducer, > ? ? fontsLoaded: fontsLoadedReducer, > ? ? restoreDeletion: restoreDeletionReducer, > ? ? targets: targetReducer, > ? ? timeout: timeoutReducer, > ? ? toolbox: toolboxReducer, > ? ? vm: vmReducer, > ? ? vmStatus: vmStatusReducer, > ? ? userState: userStateReducer > }); > ~~~ > > 下面去container / gui.jsx中為里面定義的GUI Component添加loginState這個道具,使用標識用戶是否登錄: > > > ~~~ > GUI.propTypes = { > ? ? assetHost: PropTypes.string, > ? ? children: PropTypes.node, > ? ? cloudHost: PropTypes.string, > ? ? error: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), > ? ? fetchingProject: PropTypes.bool, > ? ? intl: intlShape, > ? ? isError: PropTypes.bool, > ? ? isLoading: PropTypes.bool, > ? ? isScratchDesktop: PropTypes.bool, > ? ? isShowingProject: PropTypes.bool, > ? ? loadingStateVisible: PropTypes.bool, > ? ? onProjectLoaded: PropTypes.func, > ? ? onSeeCommunity: PropTypes.func, > ? ? onStorageInit: PropTypes.func, > ? ? onUpdateProjectId: PropTypes.func, > ? ? onUpdateProjectTitle: PropTypes.func, > ? ? onUpdateReduxProjectTitle: PropTypes.func, > ? ? onVmInit: PropTypes.func, > ? ? projectHost: PropTypes.string, > ? ? projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), > ? ? projectTitle: PropTypes.string, > ? ? telemetryModalVisible: PropTypes.bool, > ? ? vm: PropTypes.instanceOf(VM).isRequired, > ? ? loginState: PropTypes.bool > }; > ~~~ > > 這個`loginState`道具的狀態值來自于user-state.js中getIsLogined中檢測當前的loginState(指狀態中的)是否等于UserState.LOGINED: > > > ~~~ > const mapStateToProps = state => { > ? ? const loadingState = state.scratchGui.projectState.loadingState; > ? ? const loginState = state.scratchGui.userState.loginState; > ? ? return { > ? ? ? ? activeTabIndex: state.scratchGui.editorTab.activeTabIndex, > ? ? ? ? alertsVisible: state.scratchGui.alerts.visible, > ? ? ? ? backdropLibraryVisible: state.scratchGui.modals.backdropLibrary, > ? ? ? ? blocksTabVisible: state.scratchGui.editorTab.activeTabIndex === BLOCKS_TAB_INDEX, > ? ? ? ? cardsVisible: state.scratchGui.cards.visible, > ? ? ? ? connectionModalVisible: state.scratchGui.modals.connectionModal, > ? ? ? ? costumeLibraryVisible: state.scratchGui.modals.costumeLibrary, > ? ? ? ? costumesTabVisible: state.scratchGui.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, > ? ? ? ? error: state.scratchGui.projectState.error, > ? ? ? ? isError: getIsError(loadingState), > ? ? ? ? isFullScreen: state.scratchGui.mode.isFullScreen, > ? ? ? ? isPlayerOnly: state.scratchGui.mode.isPlayerOnly, > ? ? ? ? isRtl: state.locales.isRtl, > ? ? ? ? isShowingProject: getIsShowingProject(loadingState), > ? ? ? ? loadingStateVisible: state.scratchGui.modals.loadingProject, > ? ? ? ? projectId: state.scratchGui.projectState.projectId, > ? ? ? ? soundsTabVisible: state.scratchGui.editorTab.activeTabIndex === SOUNDS_TAB_INDEX, > ? ? ? ? targetIsStage: ( > ? ? ? ? ? ? state.scratchGui.targets.stage && > ? ? ? ? ? ? state.scratchGui.targets.stage.id === state.scratchGui.targets.editingTarget > ? ? ? ? ), > ? ? ? ? telemetryModalVisible: state.scratchGui.modals.telemetryModal, > ? ? ? ? tipsLibraryVisible: state.scratchGui.modals.tipsLibrary, > ? ? ? ? vm: state.scratchGui.vm, > ? ? ? ? loginState: getIsLogined(loginState) > ? ? }; > }; > ~~~ > > 現在container / gui.jsx中定義的Component GUI具有登錄狀態屬性了,我們要把它傳到menu-bar中,因為我們要在menu-bar中去控制右上角的顯示狀態。 在這個GUI組件中使用了components / gui / gui.jsx定義的GUIComponent這個組件,GUIComponent定義了整個項目的基本樣式結構中,可以找到對MenuBar的使用。 首先,在GUIComponent的定義中日期之前定義的`loginState`: > > > ~~~ > const GUIComponent = props => { > ? ? const { > ? ? ? ? accountNavOpen, > ? ? ? ? activeTabIndex, > ? ? ? ? alertsVisible, > ? ? ? ? authorId, > ? ? ? ? authorThumbnailUrl, > ? ? ? ? authorUsername, > ? ? ? ? basePath, > ? ? ? ? backdropLibraryVisible, > ? ? ? ? backpackHost, > ? ? ? ? backpackVisible, > ? ? ? ? blocksTabVisible, > ? ? ? ? cardsVisible, > ? ? ? ? canCreateNew, > ? ? ? ? canEditTitle, > ? ? ? ? canRemix, > ? ? ? ? canSave, > ? ? ? ? canCreateCopy, > ? ? ? ? canShare, > ? ? ? ? canUseCloud, > ? ? ? ? children, > ? ? ? ? connectionModalVisible, > ? ? ? ? costumeLibraryVisible, > ? ? ? ? costumesTabVisible, > ? ? ? ? enableCommunity, > ? ? ? ? intl, > ? ? ? ? isCreating, > ? ? ? ? isFullScreen, > ? ? ? ? isPlayerOnly, > ? ? ? ? isRtl, > ? ? ? ? isShared, > ? ? ? ? loading, > ? ? ? ? renderLogin, > ? ? ? ? onClickAccountNav, > ? ? ? ? onCloseAccountNav, > ? ? ? ? onLogOut, > ? ? ? ? onOpenRegistration, > ? ? ? ? onToggleLoginOpen, > ? ? ? ? onUpdateProjectTitle, > ? ? ? ? onActivateCostumesTab, > ? ? ? ? onActivateSoundsTab, > ? ? ? ? onActivateTab, > ? ? ? ? onClickLogo, > ? ? ? ? onExtensionButtonClick, > ? ? ? ? onProjectTelemetryEvent, > ? ? ? ? onRequestCloseBackdropLibrary, > ? ? ? ? onRequestCloseCostumeLibrary, > ? ? ? ? onRequestCloseTelemetryModal, > ? ? ? ? onSeeCommunity, > ? ? ? ? onShare, > ? ? ? ? onTelemetryModalCancel, > ? ? ? ? onTelemetryModalOptIn, > ? ? ? ? onTelemetryModalOptOut, > ? ? ? ? showComingSoon, > ? ? ? ? soundsTabVisible, > ? ? ? ? stageSizeMode, > ? ? ? ? targetIsStage, > ? ? ? ? telemetryModalVisible, > ? ? ? ? tipsLibraryVisible, > ? ? ? ? vm, > ? ? ? ? loginState, > ? ? ? ? ...componentProps > ? ? } = omit(props, 'dispatch'); > ? ? ... > ~~~ > > 再在使用MenuBar的地方也為MenuBar定義`loginState`屬性,它的值就是GUIComponent傳進來的`loginState`的值: > > > 最后修改components / menu-bar.jsx中的MenuBar組件的顯示,將右上角替換成: > ? ? ? ? ? ? ? ? ? ? ? ? ? ? {this.props.loginState ? ( > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? className={classNames( > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? styles.menuBarItem, > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? styles.hoverable, > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? styles.mystuffButton > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? )} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? > > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? className={styles.mystuffIcon} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? src={mystuffIcon} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /> > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id="account-nav" > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? place={this.props.isRtl ? 'right' : 'left'} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? > > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? className={classNames( > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? styles.menuBarItem, > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? styles.hoverable, > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? styles.accountNavMenu > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? )} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? > > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? className={styles.profileIcon} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? src={profileIcon} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /> > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {'scratch-cat'} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? className={styles.dropdownCaretIcon} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? src={dropdownCaret} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /> > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ) : Login} 如果用戶已登錄,就顯示頭像和姓名的樣式(具體的用戶信息需要跟后臺打通,我們后面再實現): ![](https://img-blog.csdnimg.cn/20200127181021798.png) 否則顯示登錄按鈕: ![](https://img-blog.csdnimg.cn/20200127181041268.png) 我們可以通過修改reducers / user-state.js中的loginState的初始值來查看效果: > loginState: UserState.NOT\_LOGINED > loginState: UserState.LOGINED 這個值我們會在后面根據用戶登錄的token去獲取。 為了與項目整體風格一致,我們修改這個登錄按鈕的樣式,在菜單欄目錄中添加login-button.css和login-button.jsx文件,內容分別如下: > ?? > > ~~~ > @import "../../css/colors.css"; > > .login-button { background: $data-primary;} > ~~~ > > > 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-button.css'; > > const LoginButton = ({ > > ? ? className, > > ? ? onClick > > }) => ( > > ? ? ? ? className={classNames( > > ? ? ? ? ? ? className, > > ? ? ? ? ? ? styles.loginButton > > ? ? ? ? )} > > ? ? ? ? onClick={onClick} > > ? ? > > > ? ? ? ? ? ? defaultMessage="Login" > > ? ? ? ? ? ? description="Label for login" > > ? ? ? ? ? ? id="gui.menuBar.login" > > ? ? ? ? /> > > ); > > LoginButton.propTypes = { > > ? ? className: PropTypes.string, > > ? ? onClick: PropTypes.func > > }; > > LoginButton.defaultProps = { > > ? ? onClick: () => {} > > }; > > export default LoginButton; 然后在menu-bar.jsx中如下使用: > 這樣看起來就好看多了: ![](https://img-blog.csdnimg.cn/20200127181254620.png) 好了,這里接收完成后,我們接下來就可以實現一個后臺系統,然后對接后臺系統登錄和獲取用戶信息了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看