├── .gitignore ├── anonymous-cli-metrics.json ├── learn-shopCart ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── component │ │ └── cartSimple.js │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── learn ├── .gitignore ├── .vscode │ └── settings.json ├── README.md ├── config-overrides.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.js │ ├── components │ │ ├── ButtonTest.js │ │ ├── CommentVs.js │ │ ├── ContextSample.js │ │ ├── Hoc.js │ │ ├── Hookstest.js │ │ ├── KFormCreate.js │ │ ├── Lifecycle.js │ │ └── PureComponentTest.js │ └── index.js └── yarn.lock ├── nextjs-github ├── .babelrc ├── components │ ├── Layout.jsx │ └── comp.jsx ├── demo.js ├── next-create │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── pages │ │ └── index.js │ ├── public │ │ ├── favicon.ico │ │ └── zeit.svg │ └── yarn.lock ├── next.config.js ├── package-lock.json ├── package.json ├── pages │ ├── _app.js │ ├── _document.js │ ├── a.js │ ├── index.js │ └── test │ │ └── b.js ├── readme.md ├── server.js ├── test │ └── test.css └── yarn.lock ├── react-base ├── README.md ├── anonymous-cli-metrics.json ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── Button.jsx │ ├── data.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── react-blog ├── .gitignore ├── README.md ├── config │ ├── env.js │ ├── getHttpsConfig.js │ ├── jest │ │ ├── cssTransform.js │ │ └── fileTransform.js │ ├── modules.js │ ├── paths.js │ ├── pnpTs.js │ ├── webpack.config.js │ └── webpackDevServer.config.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ ├── particles1.json │ ├── particles2.json │ └── robots.txt ├── scripts │ ├── build.js │ ├── start.js │ └── test.js ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── Router │ │ ├── admin.js │ │ ├── index.js │ │ └── web.js │ ├── api │ │ └── index.js │ ├── assets │ │ ├── img │ │ │ └── avatar.jpg │ │ └── root.css │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── pages │ │ ├── admin │ │ │ ├── home │ │ │ │ └── index.js │ │ │ ├── layout │ │ │ │ └── index.js │ │ │ └── login │ │ │ │ ├── index.js │ │ │ │ └── index.less │ │ └── web │ │ │ ├── about │ │ │ ├── about.less │ │ │ └── index.js │ │ │ ├── archive │ │ │ ├── index.js │ │ │ └── index.less │ │ │ ├── header │ │ │ ├── index.js │ │ │ └── index.less │ │ │ ├── layout │ │ │ ├── index.js │ │ │ └── index.less │ │ │ ├── list │ │ │ ├── list.js │ │ │ └── list.less │ │ │ ├── sider │ │ │ ├── index.js │ │ │ └── index.less │ │ │ └── star │ │ │ ├── index.js │ │ │ └── star.less │ ├── requireLogin.js │ ├── serviceWorker.js │ ├── setupTests.js │ └── utils(公共方法) │ │ ├── index.js │ │ └── loadable.js └── yarn.lock ├── react-comment ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── CommentInput.jsx │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── react-demo ├── LifeCycle.js ├── build │ ├── babel.min.js │ ├── jquery.min.js │ ├── prop-types.js │ ├── react-dom.development.js │ ├── react.development.js │ └── react.js ├── demo1 │ └── index.html ├── demo10 │ └── index.html ├── demo11 │ └── index.html ├── demo12 │ └── index.html ├── demo2 │ └── index.html ├── demo3 │ └── index.html ├── demo4 │ └── index.html ├── demo5 │ └── index.html ├── demo6 │ └── index.html ├── demo7 │ └── index.html ├── demo8 │ └── index.html └── demo9(实现节流) │ └── index.html ├── react-hoc ├── .gitignore ├── README.md ├── config │ ├── env.js │ ├── getHttpsConfig.js │ ├── jest │ │ ├── cssTransform.js │ │ └── fileTransform.js │ ├── modules.js │ ├── paths.js │ ├── pnpTs.js │ ├── webpack.config.js │ └── webpackDevServer.config.js ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── scripts │ ├── build.js │ ├── start.js │ └── test.js ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── component │ │ ├── example1 │ │ │ └── index.js │ │ ├── example2 │ │ │ └── index.js │ │ ├── example3 │ │ │ ├── OperateRefsHOC.js │ │ │ ├── index.js │ │ │ └── user.js │ │ └── useRef │ │ │ ├── Use.js │ │ │ └── index.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── react-hook ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── component │ │ ├── useEffect │ │ │ ├── index.js │ │ │ ├── indexHook.js │ │ │ └── makeUnmount.js │ │ └── useState │ │ │ ├── index.js │ │ │ └── indexHook.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── react-jianshu ├── .gitignore ├── README.md ├── package.json ├── public │ ├── api │ │ ├── detail.json │ │ ├── home.json │ │ ├── homeList.json │ │ └── login.json │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.js │ ├── common │ │ └── header │ │ │ ├── index.js │ │ │ ├── store │ │ │ ├── actionCreator.js │ │ │ ├── actionTypes.js │ │ │ ├── index.js │ │ │ └── reducer.js │ │ │ └── style.js │ ├── index.js │ ├── pages │ │ ├── detail │ │ │ ├── index.js │ │ │ ├── loadable.js │ │ │ ├── store │ │ │ │ ├── actionCreators.js │ │ │ │ ├── constants.js │ │ │ │ ├── index.js │ │ │ │ └── reducer.js │ │ │ └── style.js │ │ ├── home │ │ │ ├── components │ │ │ │ ├── List.js │ │ │ │ ├── Recommend.js │ │ │ │ ├── Topic.js │ │ │ │ └── Writer.js │ │ │ ├── index.js │ │ │ ├── store │ │ │ │ ├── actionCreators.js │ │ │ │ ├── constants.js │ │ │ │ ├── index.js │ │ │ │ └── reducer.js │ │ │ └── style.js │ │ ├── login │ │ │ ├── index.js │ │ │ ├── store │ │ │ │ ├── actionCreators.js │ │ │ │ ├── constants.js │ │ │ │ ├── index.js │ │ │ │ └── reducer.js │ │ │ └── style.js │ │ └── write │ │ │ └── index.js │ ├── static │ │ ├── icon-font │ │ │ ├── iconfont.eot │ │ │ ├── iconfont.js │ │ │ ├── iconfont.json │ │ │ ├── iconfont.svg │ │ │ ├── iconfont.ttf │ │ │ ├── iconfont.woff │ │ │ └── iconfont.woff2 │ │ └── logo.png │ ├── store │ │ ├── index.js │ │ └── reducer.js │ └── style.js ├── yarn.lock └── 加载更多.md ├── react-react-redux ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── TodoList.js │ ├── index.js │ └── store │ │ ├── index.js │ │ └── reducer.js └── yarn.lock ├── react-redux ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── redux 原理图.jpg ├── src │ ├── App.css │ ├── App.test.js │ ├── TodoList.js │ ├── TodoListUI.js │ ├── assets │ │ └── list.json │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ ├── setupTests.js │ └── store │ │ ├── actionCreators.js │ │ ├── actionTypes.js │ │ ├── index.js │ │ ├── reducer.js │ │ └── sagas.js └── yarn.lock ├── react-router-antd ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── pages │ │ └── Layout.jsx │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── react-router ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── readme.md └── weather ├── .gitignore ├── README.md ├── config ├── env.js ├── getHttpsConfig.js ├── jest │ ├── cssTransform.js │ └── fileTransform.js ├── modules.js ├── paths.js ├── pnpTs.js ├── webpack.config.js └── webpackDevServer.config.js ├── package-lock.json ├── package.json ├── public ├── city │ ├── citylist.json │ ├── citys.json │ └── hotcity.json ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── scripts ├── build.js ├── start.js └── test.js ├── src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg ├── pages │ ├── main │ │ ├── component │ │ │ ├── cloudy.js │ │ │ └── style.js │ │ ├── index.js │ │ ├── loadable.js │ │ └── style.js │ ├── search │ │ ├── index.js │ │ ├── loadable.js │ │ └── style.js │ └── test │ │ └── index.js ├── serviceWorker.js ├── setupTests.js ├── static │ ├── iconfont │ │ ├── iconfont.eot │ │ ├── iconfont.js │ │ ├── iconfont.json │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ └── img │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 中雨.png │ │ ├── 多云.png │ │ ├── 大雨.png │ │ ├── 小雨.png │ │ ├── 晴.png │ │ ├── 阴.png │ │ ├── 阵雨.png │ │ └── 雷阵雨.png └── store │ ├── actionCreators.js │ ├── actionTypes.js │ ├── index.js │ └── reducer.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | -------------------------------------------------------------------------------- /anonymous-cli-metrics.json: -------------------------------------------------------------------------------- 1 | {"metricId":"c2f8f15e-f1da-4788-b653-df21b1638cfe","metrics":{"from":"2020-01-08T02:30:34.361Z","to":"2020-01-08T02:30:34.361Z","successfulInstalls":1,"failedInstalls":0}} -------------------------------------------------------------------------------- /learn-shopCart/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /learn-shopCart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learn-shopcart", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-scripts": "3.4.0" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "build": "react-scripts build", 16 | "test": "react-scripts test", 17 | "eject": "react-scripts eject" 18 | }, 19 | "eslintConfig": { 20 | "extends": "react-app" 21 | }, 22 | "browserslist": { 23 | "production": [ 24 | ">0.2%", 25 | "not dead", 26 | "not op_mini all" 27 | ], 28 | "development": [ 29 | "last 1 chrome version", 30 | "last 1 firefox version", 31 | "last 1 safari version" 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /learn-shopCart/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/learn-shopCart/public/favicon.ico -------------------------------------------------------------------------------- /learn-shopCart/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/learn-shopCart/public/logo192.png -------------------------------------------------------------------------------- /learn-shopCart/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/learn-shopCart/public/logo512.png -------------------------------------------------------------------------------- /learn-shopCart/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /learn-shopCart/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /learn-shopCart/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /learn-shopCart/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /learn-shopCart/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | // import App from './App'; 4 | import CartSimple from './component/cartSimple' 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /learn-shopCart/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /learn/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /learn/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "javascript.implicitProjectConfig.experimentalDecorators": true 3 | } -------------------------------------------------------------------------------- /learn/README.md: -------------------------------------------------------------------------------- 1 | ## super() 函数是用于调用父类(超类)的一个方法。 -------------------------------------------------------------------------------- /learn/config-overrides.js: -------------------------------------------------------------------------------- 1 | const { override, 2 | fixBabelImports,addBabelPlugins 3 | } = require("customize-cra"); 4 | 5 | 6 | module.exports = override( 7 | // antd按需加载 8 | fixBabelImports( 9 | "import", { libraryName: "antd", libraryDirectory: "es", style: "css" } 10 | ), 11 | addBabelPlugins( 12 | ['@babel/plugin-proposal-decorators', { legacy: true }], 13 | ) 14 | ); -------------------------------------------------------------------------------- /learn/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learn", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@babel/plugin-proposal-decorators": "^7.7.0", 7 | "antd": "^3.12.4", 8 | "babel-plugin-import": "^1.11.0", 9 | "react": "^16.7.0", 10 | "react-app-rewired": "^2.1.5", 11 | "react-dom": "^16.7.0", 12 | "react-scripts": "2.1.3" 13 | }, 14 | "babel": { 15 | "plugins": [ 16 | [ 17 | "@babel/plugin-proposal-decorators", 18 | { 19 | "legacy": true 20 | } 21 | ] 22 | ], 23 | "presets": [ 24 | "@babel/preset-env" 25 | ] 26 | }, 27 | "scripts": { 28 | "start": "react-app-rewired start", 29 | "build": "react-app-rewired build", 30 | "test": "react-app-rewired test", 31 | "eject": "react-app-rewired eject" 32 | }, 33 | "eslintConfig": { 34 | "extends": "react-app" 35 | }, 36 | "browserslist": [ 37 | ">0.2%", 38 | "not dead", 39 | "not ie <= 11", 40 | "not op_mini all" 41 | ], 42 | "devDependencies": { 43 | "customize-cra": "^0.9.1", 44 | "less": "^3.10.3", 45 | "less-loader": "^5.0.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /learn/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/learn/public/favicon.ico -------------------------------------------------------------------------------- /learn/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/learn/public/logo192.png -------------------------------------------------------------------------------- /learn/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/learn/public/logo512.png -------------------------------------------------------------------------------- /learn/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /learn/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /learn/src/App.js: -------------------------------------------------------------------------------- 1 | import React,{ Component } from 'react' 2 | 3 | class App extends Component { 4 | render () { // jsx 5 | return
6 | 7 |
8 | } 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /learn/src/components/ButtonTest.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Button from 'antd/lib/button' 3 | import 'antd/dist/antd.css' 4 | 5 | class ButtonTest extends Component { 6 | render () { 7 | return ( 8 |
9 | 10 |
11 | ) 12 | } 13 | } 14 | export default ButtonTest -------------------------------------------------------------------------------- /learn/src/components/CommentVs.js: -------------------------------------------------------------------------------- 1 | import React,{ Component } from 'react' 2 | 3 | // 容器组件 4 | export default class CommentVs extends Component { 5 | constructor (props) { 6 | super(props) 7 | this.state = { 8 | comment: [] 9 | } 10 | } 11 | componentDidMount () { 12 | setTimeout(() => { 13 | this.setState({ 14 | comment: [ 15 | { body: 'react is very good', author: 'facebook'}, 16 | { body: 'vue is very good', author: '尤雨溪'} 17 | ] 18 | }) 19 | }, 1000) 20 | } 21 | render () { 22 | return ( 23 |
24 | { 25 | this.state.comment.map((item, i) => ( 26 | 27 | )) 28 | } 29 |
30 | ) 31 | } 32 | } 33 | 34 | // 展示组件 35 | function Comment({ data }) { 36 | return ( 37 |
38 |

{data.body}

39 |

--{data.author}

40 |
41 | ) 42 | } -------------------------------------------------------------------------------- /learn/src/components/ContextSample.js: -------------------------------------------------------------------------------- 1 | // 组件跨层级的上下文通信, 可以使用context 这种模式下会有两个角色 Provide Consumer 2 | // Provide为外层组件 用来提供数据 3 | // Consumer -> 内部需要数据时用 Consumer 来读取 4 | import React , { Component } from 'react'; 5 | 6 | //1. 创建上下文 7 | const Context = React.createContext() 8 | 9 | const store = { 10 | name: '恭喜你中了一等奖', 11 | sayHi() { 12 | console.log(this.name) 13 | } 14 | } 15 | 16 | const withProvider = Comp => props => ( 17 | 18 | 19 | 20 | 21 | ) 22 | const withConsumer = Comp => props => ( 23 | 24 | {/* 必须内嵌一个函数 */} 25 | {value => } 26 | 27 | ) 28 | 29 | @withConsumer 30 | //withConsumer(Inner) 31 | class Inner extends Component { 32 | render() { 33 | console.log('Inner') 34 | return ( 35 |
{this.props.value.name}
36 | ) 37 | } 38 | } 39 | 40 | @withProvider 41 | class ContextSample extends Component { 42 | render () { 43 | console.log('ContextSample') 44 | return ( 45 |
46 | 47 |
48 | ) 49 | } 50 | } 51 | 52 | export default ContextSample 53 | -------------------------------------------------------------------------------- /learn/src/components/Hoc.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | // 高阶组件--链式调用 4 | const withName = Comp => { 5 | class NewComponent extends Component { 6 | componentDidMount() { 7 | console.log('do somthing') 8 | } 9 | render () { 10 | return 11 | } 12 | } 13 | 14 | return NewComponent; 15 | } 16 | 17 | const withLog = Comp => { 18 | console.log(Comp.name + '渲染了') 19 | return props => 20 | } 21 | 22 | // // ES6装饰器简化高阶组件的写法 必须要安装@babel/plugin-proposal-decorators 23 | // @withLog // withLog(Jpsite) 24 | // @withName // withName(withLog) 25 | // @withLog 26 | class Jpsite extends Component { 27 | render () { 28 | return ( 29 |
30 | {this.props.state} - {this.props.name} 31 |
32 | ) 33 | } 34 | } 35 | export default withName(withLog(App)) // 链式调用 36 | // export default Jpsite -------------------------------------------------------------------------------- /learn/src/components/Hookstest.js: -------------------------------------------------------------------------------- 1 | // Hook(钩子函数) 它可以让你在不编写 class 的情况下使用 state 内部状态以及其他的 React 特性 2 | 3 | // 使用state Hook 4 | import React, { useState, useEffect } from 'react' 5 | 6 | // class HooksTest extends Component { 7 | // constructor (props) { 8 | // super(props) 9 | 10 | // this.state = { 11 | // count: 0 12 | // } 13 | // } 14 | // } 15 | 16 | export default function HooksTest () { 17 | // useState(initalState), 接收初始状态, 返回一个状态变量和它的更新函数, 属性名可以自定义 18 | // 声明一个新的叫做 "count" 的 state 变量 19 | const [count,setCount] = useState(0) 20 | 21 | // 数据获取 设置订阅 以及手动更改React组件中的DOM -- 副作用 22 | useEffect(() => { 23 | document.title = `您点击了 ${count} 次`; 24 | }) 25 | return ( 26 |
27 |

You clicked {count} times

28 | {/* 调用setCount, 修改状态count */} 29 | 30 |
31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /learn/src/components/Lifecycle.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | class LifeCycle extends Component { 4 | constructor (props) { 5 | super(props) 6 | console.log('1. 构造函数') 7 | this.state = { 8 | msg: '来自属性传递' + props.prop 9 | } 10 | } 11 | componentWillMount () { 12 | // 此时可以访问属性和状态,可以进行api调用 但是没有办法做dom相关操作 13 | // console.log(this.state.msg) 14 | console.log('2. 组件将要挂载') 15 | } 16 | componentDidMount () { 17 | // 组件已经渲染完成, 可以进行状态更新操作 18 | console.log('3. 组件已挂载') 19 | } 20 | componentWillReceiveProps () { 21 | // 父组件传递的属性有变化, 做相应的操作 22 | console.log('4. 组件属性更新了') 23 | } 24 | shouldComponentUpdate () { 25 | // 组件是否需要更新, 返回boolean 26 | console.log('5. 组件是否需要更新?') 27 | return true 28 | } 29 | componentWillUpdate () { 30 | console.log('6. 组件将要更新') 31 | } 32 | componentDidUpdate () { 33 | console.log('7. 组件已经更新') 34 | } 35 | render () { 36 | console.log('组件渲染') 37 | return ( 38 |
组件生命周期探究
39 | ) 40 | } 41 | } 42 | 43 | export default class extends Component { 44 | constructor(props){ 45 | super(props) 46 | this.state = { 47 | someProp: '北辰' 48 | } 49 | 50 | setTimeout (() => { 51 | this.setState({ 52 | someProp: 'beichen' 53 | }) 54 | }, 2000) 55 | } 56 | render () { 57 | return 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /learn/src/components/PureComponentTest.js: -------------------------------------------------------------------------------- 1 | import React, {Component, PureComponent} from 'react' 2 | // PureComponent 组件, 其实就是定制化后的 shouldComponentUpdate 的加强 3 | 4 | // shouldComponentUpdate 的加强版 5 | class PureComponentTest extends Component { 6 | constructor(props){ 7 | super(props) 8 | 9 | this.state = { 10 | comment: [ 11 | { body: 'react is very good', author: 'facebook'}, 12 | { body: 'vue is very good', author: '尤雨溪'} 13 | ] 14 | } 15 | setTimeout (() => { 16 | this.setState({ 17 | comment: [ 18 | { body: 'react is very good', author: 'facebook'}, 19 | { body: 'vue is very good', author: '尤雨溪'} 20 | ] 21 | }) 22 | }, 2000) 23 | } 24 | 25 | render () { 26 | // console.log('render') 27 | return ( 28 |
29 | {this.state.comment.map((c,i) => ( 30 | 31 | ))} 32 |
33 | ) 34 | } 35 | } 36 | 37 | // PureComponent节流没必要更新的时候不更新 Component只要数据源被操作就会更新 38 | // class Comment extends Component 39 | class Comment extends PureComponent { 40 | constructor(props){ 41 | super(props) 42 | } 43 | // shouldComponentUpdate(nextProp) { 44 | // console.log(nextProp) 45 | // if (nextProp.data.body === this.props.data.body && nextProp.data.author === this.props.data.author) { 46 | // console.log(false) 47 | // return false 48 | // } 49 | // console.log(true) 50 | // return true 51 | // } 52 | render () { 53 | console.log('render') 54 | return ( 55 |
56 |

{this.props.data.body}

57 |

--{this.props.data.author}

58 |
59 | ) 60 | } 61 | } 62 | 63 | export default PureComponentTest; 64 | -------------------------------------------------------------------------------- /nextjs-github/.babelrc: -------------------------------------------------------------------------------- 1 | // babel配置文件 2 | { 3 | "presets": ["next/babel"], 4 | "plugins": [ 5 | ["import", { 6 | "libraryName": "antd" 7 | }], 8 | [ 9 | "styled-components", {"ssr": true} 10 | ] 11 | ] 12 | } -------------------------------------------------------------------------------- /nextjs-github/components/Layout.jsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import { Button } from 'antd' 3 | 4 | export default ({ children }) => ( 5 | <> 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | {} 14 |
15 |
{children}
16 | 17 | ) -------------------------------------------------------------------------------- /nextjs-github/components/comp.jsx: -------------------------------------------------------------------------------- 1 | export default ({ children }) => -------------------------------------------------------------------------------- /nextjs-github/demo.js: -------------------------------------------------------------------------------- 1 | // 启动一个后端服务 2 | const Koa = require('koa') 3 | const next = require('next') 4 | const Router = require('koa-router') 5 | 6 | const dev = process.env.NODE_ENV !== 'production' 7 | const app = next({ dev }) 8 | 9 | const handle = app.getRequestHandler() 10 | 11 | // app.prepare().then(() => { 12 | // 创建koa服务 13 | const server = new Koa() 14 | const router = new Router() 15 | 16 | router.get('/test/:id', (ctx) => { 17 | // ctx.body = `

request /test ${ctx.params.id}

` 18 | ctx.body = { success: true } 19 | ctx.set('Content-Type', 'application/js') 20 | }) 21 | 22 | server.use(async (ctx, next) => { 23 | // const path = ctx.path 24 | // const method = ctx.method 25 | // ctx.body= `Koa Render ${method} ${path}` 26 | await next() 27 | }) 28 | // server.use(async (ctx, next) => { 29 | // ctx.body= 'Koa Render2' 30 | // }) 31 | // node一块的中间件...? 32 | // async await 33 | // server.use(async (ctx, next) => { // 中间件就是一个函数 34 | // await handle(ctx.req, ctx.res) 35 | // ctx.respond = false 36 | // }) 37 | //router.routes()中间件 38 | server.use(router.routes()) 39 | 40 | server.listen(3000, () => { 41 | console.log('koa server listening on 3000') 42 | }) 43 | // }) -------------------------------------------------------------------------------- /nextjs-github/next-create/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | .env* 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /nextjs-github/next-create/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 16 | 17 | ## Learn More 18 | 19 | To learn more about Next.js, take a look at the following resources: 20 | 21 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 22 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 23 | 24 | You can check out [the Next.js GitHub repository](https://github.com/zeit/next.js/) - your feedback and contributions are welcome! 25 | 26 | ## Deploy on ZEIT Now 27 | 28 | The easiest way to deploy your Next.js app is to use the [ZEIT Now Platform](https://zeit.co/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 29 | 30 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 31 | -------------------------------------------------------------------------------- /nextjs-github/next-create/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-create", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "next": "9.3.1", 12 | "react": "16.13.1", 13 | "react-dom": "16.13.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nextjs-github/next-create/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/nextjs-github/next-create/public/favicon.ico -------------------------------------------------------------------------------- /nextjs-github/next-create/public/zeit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /nextjs-github/next.config.js: -------------------------------------------------------------------------------- 1 | // 配置使其能外部引入css微博华北 2 | const withCss = require('@zeit/next-css') 3 | 4 | if (typeof require !== 'undefined') { 5 | require.extensions['.css'] = (file) => {} 6 | } 7 | 8 | module.exports = withCss({}) -------------------------------------------------------------------------------- /nextjs-github/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "y", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "node server.js", 9 | "build": "next build", 10 | "start": "next start" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@zeit/next-css": "^1.0.1", 16 | "antd": "^4.0.4", 17 | "babel-plugin-import": "^1.13.0", 18 | "babel-plugin-styled-components": "^1.10.7", 19 | "koa": "^2.11.0", 20 | "koa-router": "^8.0.8", 21 | "next": "^9.3.1", 22 | "react": "^16.13.1", 23 | "react-dom": "^16.13.1", 24 | "styled-components": "^5.0.1" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /nextjs-github/pages/_app.js: -------------------------------------------------------------------------------- 1 | import App from 'next/app' 2 | 3 | import 'antd/dist/antd.css' 4 | 5 | import Layout from '../components/Layout' 6 | 7 | class MyApp extends App { 8 | 9 | static async getInitialProps({ Component, ctx }) { 10 | console.log('app init') 11 | let pageProps 12 | 13 | if (Component.getInitialProps) { 14 | // ctx 上下文 15 | pageProps = await Component.getInitialProps(ctx) 16 | } 17 | return { 18 | pageProps 19 | } 20 | } 21 | 22 | render() { 23 | const { Component, pageProps } = this.props 24 | 25 | return( 26 | 27 | 28 | 29 | ) 30 | } 31 | } 32 | 33 | export default MyApp -------------------------------------------------------------------------------- /nextjs-github/pages/_document.js: -------------------------------------------------------------------------------- 1 | import Document, { Html, Head, Main, NextScript } from 'next/document' 2 | import { ServerStyleSheet } from 'styled-components' 3 | 4 | // HOC 5 | function withLog (Comp) { 6 | return (props) => { 7 | console.log(props) 8 | return 9 | } 10 | } 11 | 12 | class myDocument extends Document { 13 | static async getInitialProps(ctx) { 14 | const sheet = new ServerStyleSheet() 15 | 16 | const originalRenderPage = ctx.renderPage 17 | 18 | try{ 19 | ctx.renderPage = () => originalRenderPage({ 20 | enhanceApp: App => (props) => sheet.collectStyles(), 21 | enhanceComponent: Component => withLog(Component) 22 | }) 23 | const props = await Document.getInitialProps(ctx) 24 | return { 25 | ...props, 26 | styles: <>{props.styles}{sheet.getStyleElement()} 27 | } 28 | } finally{ 29 | sheet.seal() 30 | } 31 | 32 | 33 | 34 | } 35 | 36 | 37 | 38 | render() { 39 | return ( 40 | 41 | 42 | 43 |
44 | 45 | 46 | 47 | ) 48 | } 49 | } 50 | 51 | export default myDocument -------------------------------------------------------------------------------- /nextjs-github/pages/a.js: -------------------------------------------------------------------------------- 1 | import { withRouter } from 'next/router' 2 | import Link from 'next/link' 3 | import Comp from '../components/comp' 4 | import Head from 'next/head' 5 | import styled from 'styled-components' 6 | 7 | const Title = styled.h1` 8 | color: yellow; 9 | font-size:40px; 10 | ` 11 | const color = '#113366' 12 | 13 | const A = ({ router, name }) => ( 14 | <> 15 | This is title 16 | 17 | {router.query.id}{name} 18 | 19 | 20 | 28 | 29 | ) 30 | 31 | A.getInitialProps = async(ctx) => { 32 | 33 | const promise = new Promise((resolve, reject) => { 34 | setTimeout(() => { 35 | resolve({ 36 | name: 'wn' 37 | }) 38 | }, 1000) 39 | }) 40 | return await promise 41 | } 42 | 43 | export default withRouter(A) -------------------------------------------------------------------------------- /nextjs-github/pages/index.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Router from 'next/router' 3 | import { Button } from 'antd' 4 | 5 | const events = [ 6 | 'routeChangeStart', 7 | 'routeChangeComplete', 8 | 'routeChangeError', 9 | 'beforeHistoryChange', 10 | 'hashChangeStart', 11 | 'hashChangeComplete' 12 | ] 13 | 14 | function makeEvent(type) { 15 | return (...args) => { 16 | console.log(type, ...args) 17 | } 18 | } 19 | 20 | events.forEach(event => { 21 | Router.events.on(event, makeEvent(event)) 22 | }) 23 | 24 | export default () => { 25 | 26 | return ( 27 | <> 28 | Index 29 | 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /nextjs-github/pages/test/b.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | class MyCount extends React.Component{ 4 | state = { 5 | count: 0 6 | } 7 | 8 | componentDidMount() { 9 | this.interval = setInterval(() => { 10 | this.setState({ 11 | count: this.state.count + 1 12 | }) 13 | }, 1000); 14 | } 15 | 16 | componentWillUnmount() { 17 | if (this.interval) { 18 | clearInterval(this.interval) 19 | } 20 | } 21 | 22 | render () { 23 | return {this.state.count} 24 | } 25 | } 26 | 27 | export default MyCount -------------------------------------------------------------------------------- /nextjs-github/readme.md: -------------------------------------------------------------------------------- 1 | # nextjs 作为koa的中间件使用 2 | 3 | 数据接口 4 | 数据库的连接 5 | session状态 6 | 7 | # Router 钩子 8 | 9 | routeChangeStart 10 | routeChangeComplete 11 | routeChangeError 12 | beforeHistoryChange 13 | hashChangeStart 14 | hashChangeComplete 15 | 16 | # getInitialProps 17 | 18 | # Hooks 让函数组件具有类组件的能力 19 | 20 | # document css-in-js 21 | next/js自带模块 引入 22 | > import Document, { Html, Head, Main, NextScript } from 'next/document' -------------------------------------------------------------------------------- /nextjs-github/server.js: -------------------------------------------------------------------------------- 1 | // 启动一个后端服务 2 | const Koa = require('koa') 3 | const next = require('next') 4 | const Router = require('koa-router') 5 | 6 | const dev = process.env.NODE_ENV !== 'production' 7 | const app = next({ dev }) 8 | 9 | const handle = app.getRequestHandler() 10 | 11 | app.prepare().then(() => { 12 | // 创建koa服务 13 | const server = new Koa() 14 | const router = new Router() 15 | 16 | // 路由映射 17 | router.get('/a/:id', async (ctx) => { 18 | const id = ctx.params.id 19 | await handle(ctx.req, ctx.res,{ 20 | pathname: '/a', 21 | query: { 22 | id 23 | } 24 | }) 25 | ctx.respond = false 26 | }) 27 | 28 | server.use(router.routes()) 29 | // node一块的中间件...? 30 | // async await 31 | server.use(async (ctx, next) => { // 中间件就是一个函数 32 | await handle(ctx.req, ctx.res) 33 | ctx.respond = false 34 | }) 35 | server.listen(3000, () => { 36 | console.log('koa server listening on 3000') 37 | }) 38 | }) -------------------------------------------------------------------------------- /nextjs-github/test/test.css: -------------------------------------------------------------------------------- 1 | body{ 2 | color: red; 3 | } -------------------------------------------------------------------------------- /react-base/anonymous-cli-metrics.json: -------------------------------------------------------------------------------- 1 | {"metricId":"29cbca7f-2580-4147-9296-490899b464c1","metrics":{"from":"2020-01-08T03:37:38.079Z","to":"2020-01-08T03:37:38.079Z","successfulInstalls":1,"failedInstalls":0}} -------------------------------------------------------------------------------- /react-base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-base", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@tensorflow/tfjs-vis": "^1.3.0", 7 | "@testing-library/jest-dom": "^4.2.4", 8 | "@testing-library/react": "^9.3.2", 9 | "@testing-library/user-event": "^7.1.2", 10 | "react": "^16.12.0", 11 | "react-dom": "^16.12.0", 12 | "react-scripts": "3.3.0" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /react-base/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-base/public/favicon.ico -------------------------------------------------------------------------------- /react-base/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-base/public/logo192.png -------------------------------------------------------------------------------- /react-base/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-base/public/logo512.png -------------------------------------------------------------------------------- /react-base/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-base/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /react-base/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | .primary-class{ 5 | color: #61dafb; 6 | } 7 | .App-logo { 8 | height: 40vmin; 9 | pointer-events: none; 10 | } 11 | 12 | @media (prefers-reduced-motion: no-preference) { 13 | .App-logo { 14 | animation: App-logo-spin infinite 20s linear; 15 | } 16 | } 17 | 18 | .App-header { 19 | background-color: #282c34; 20 | min-height: 100vh; 21 | display: flex; 22 | flex-direction: column; 23 | align-items: center; 24 | justify-content: center; 25 | font-size: calc(10px + 2vmin); 26 | color: white; 27 | } 28 | 29 | .App-link { 30 | color: #61dafb; 31 | } 32 | 33 | @keyframes App-logo-spin { 34 | from { 35 | transform: rotate(0deg); 36 | } 37 | to { 38 | transform: rotate(360deg); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /react-base/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import Button from './Button' 4 | import './App.css'; 5 | 6 | function App() { 7 | let person = [{age: 16, name: '江军'}, {age:19, name:'Biec'}] 8 | // age > 18 9 | // find 声明式 10 | let p = person.find(p => p.age > 18) 11 | //命令式 12 | for(let pp of person){ 13 | if(pp.age > 17){ 14 | console.log(pp.name) 15 | } 16 | } 17 | let ages = person.map(p => PageTransitionEvent.age) 18 | 19 | let arr = [0, 1, 2] 20 | 21 | function receiveFromButton(d) { 22 | console.log('从子组件:', d); 23 | } 24 | return ( 25 |
26 | {/* 29 | { 30 | arr 31 | } 32 | { 33 | person.map((p,i)=>{ 34 | return
  • {p.name}-{p.age}
  • 35 | }) 36 | } 37 | { 38 | person.length > 3 ?

    有三个人

    :

    小于三个人

    39 | } 40 | {person.length === 2 &&

    有两个人

    } 41 |
    42 | logo 43 |

    44 | Edit src/App.js and save to reload. 45 |

    46 | 52 | Learn React 53 | 54 |
    55 |
    56 | ); 57 | } 58 | 59 | export default App; 60 | -------------------------------------------------------------------------------- /react-base/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-base/src/Button.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function Button(props) { 4 | let date = new Date().getTime(); 5 | // 通知父组件 6 | const handleClick = () => { 7 | console.log(1234); 8 | } 9 | const { type, children, receiveFromButton } = props; 10 | //父传递一个回调函数过来, 子组件通过参数通知父组件 11 | receiveFromButton(date); 12 | return ( 13 | 14 | ) 15 | } 16 | export default Button; -------------------------------------------------------------------------------- /react-base/src/data.js: -------------------------------------------------------------------------------- 1 | export function getData(nums) { 2 | let point = []; 3 | function generate() { 4 | for (let i = 0 ; i < 200; i ++) { 5 | let x = normalRandom() 6 | let y = normalRandom() 7 | point({x, y}) 8 | } 9 | } 10 | // 黄点 11 | generate(); 12 | // 蓝点 13 | generate(); 14 | return point; 15 | 16 | } 17 | 18 | function normalRandom() { 19 | let u1 = Math.random(); 20 | let u2 = Math.random(); 21 | let result = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2) 22 | return result 23 | } 24 | -------------------------------------------------------------------------------- /react-base/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react-base/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | import * as tf from '@tensorflow/tfjs' 7 | import * as tfvis from '@tensorflow/tfjs-vis' 8 | 9 | 10 | import { 11 | getData 12 | } from './data.js' 13 | 14 | window.onload = async () => { 15 | const data = getData() 16 | console.log(data) 17 | tfvis.render.scatterplot( 18 | {name: '数据'} 19 | ) 20 | } 21 | //浏览器专用的 Dom 22 | ReactDOM.render(, document.getElementById('root')); 23 | 24 | // react-native 25 | // ReactNative.render() 26 | // 核心的包: react 27 | // 平台相关的包: react-dom / react native / react-TV 28 | 29 | // If you want your app to work offline and load faster, you can change 30 | // unregister() to register() below. Note this comes with some pitfalls. 31 | // Learn more about service workers: https://bit.ly/CRA-PWA 32 | serviceWorker.unregister(); 33 | -------------------------------------------------------------------------------- /react-base/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /react-blog/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-blog/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /react-blog/config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFilename = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFilename}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /react-blog/config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /react-blog/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-blog/public/favicon.ico -------------------------------------------------------------------------------- /react-blog/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-blog/public/logo192.png -------------------------------------------------------------------------------- /react-blog/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-blog/public/logo512.png -------------------------------------------------------------------------------- /react-blog/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-blog/public/particles2.json: -------------------------------------------------------------------------------- 1 | { 2 | "particles": { 3 | "number": { 4 | "value": 160, 5 | "density": { 6 | "enable": false 7 | } 8 | }, 9 | "size": { 10 | "value": 3, 11 | "random": true, 12 | "anim": { 13 | "speed": 4, 14 | "size_min": 0.3 15 | } 16 | }, 17 | "line_linked": { 18 | "enable": false 19 | }, 20 | "move": { 21 | "random": true, 22 | "speed": 1, 23 | "direction": "top", 24 | "out_mode": "out" 25 | } 26 | }, 27 | "interactivity": { 28 | "events": { 29 | "onhover": { 30 | "enable": true, 31 | "mode": "bubble" 32 | }, 33 | "onclick": { 34 | "enable": true, 35 | "mode": "repulse" 36 | } 37 | }, 38 | "modes": { 39 | "bubble": { 40 | "distance": 250, 41 | "duration": 2, 42 | "size": 0, 43 | "opacity": 0 44 | }, 45 | "repulse": { 46 | "distance": 400, 47 | "duration": 4 48 | } 49 | } 50 | }, 51 | "retina_detect": true 52 | } 53 | -------------------------------------------------------------------------------- /react-blog/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-blog/scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | 19 | const jest = require('jest'); 20 | const execSync = require('child_process').execSync; 21 | let argv = process.argv.slice(2); 22 | 23 | function isInGitRepository() { 24 | try { 25 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 26 | return true; 27 | } catch (e) { 28 | return false; 29 | } 30 | } 31 | 32 | function isInMercurialRepository() { 33 | try { 34 | execSync('hg --cwd . root', { stdio: 'ignore' }); 35 | return true; 36 | } catch (e) { 37 | return false; 38 | } 39 | } 40 | 41 | // Watch unless on CI or explicitly running all tests 42 | if ( 43 | !process.env.CI && 44 | argv.indexOf('--watchAll') === -1 && 45 | argv.indexOf('--watchAll=false') === -1 46 | ) { 47 | // https://github.com/facebook/create-react-app/issues/5210 48 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 49 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 50 | } 51 | 52 | 53 | jest.run(argv); 54 | -------------------------------------------------------------------------------- /react-blog/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-blog/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { BrowserRouter as Router , Route, Link, Redirect } from 'react-router-dom' 3 | import Login from './pages/admin/login' 4 | import routes from './Router' 5 | import requireLogin from './requireLogin' 6 | 7 | class App extends Component { 8 | constructor(props){ 9 | super(props) 10 | } 11 | 12 | //Redirect 路由重定向 13 | render () { 14 | return ( 15 | 16 |
    17 | } /> 18 | 19 | { 20 | routes.map((route, i) => ( 21 | 24 | )) 25 | } 26 |
    27 |
    28 | ) 29 | } 30 | } 31 | 32 | export default App -------------------------------------------------------------------------------- /react-blog/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-blog/src/Router/admin.js: -------------------------------------------------------------------------------- 1 | import loadable from '../utils(公共方法)/loadable' 2 | 3 | const Home = loadable(() => import('../pages/admin/home')) 4 | 5 | const routes = [ 6 | { 7 | menu: true, 8 | icon: 'home', 9 | title: '首页', 10 | path: '/admin/page', 11 | component: Home 12 | } 13 | ] 14 | 15 | export default routes -------------------------------------------------------------------------------- /react-blog/src/Router/index.js: -------------------------------------------------------------------------------- 1 | import loadable from '../utils(公共方法)/loadable' 2 | 3 | const adminLayout = loadable(() => import('../pages/admin/layout')) 4 | const webLayout = loadable(() => import('../pages/web/layout')) 5 | 6 | const routes = [ 7 | { 8 | path: '/admin', 9 | component: adminLayout 10 | }, 11 | { 12 | path: '/web', 13 | component: webLayout 14 | } 15 | ] 16 | 17 | export default routes -------------------------------------------------------------------------------- /react-blog/src/Router/web.js: -------------------------------------------------------------------------------- 1 | import loadable from '../utils(公共方法)/loadable' 2 | import { HomeOutlined,EditOutlined, StarOutlined, TeamOutlined } from '@ant-design/icons'; 3 | const List = loadable(() => import('../pages/web/list/list')) 4 | const Archive = loadable(() => import('../pages/web/archive')) 5 | const Star = loadable(() => import('../pages/web/star')) 6 | const About = loadable(() => import('../pages/web/about')) 7 | 8 | const webRoutes = [ 9 | { 10 | menu: true, 11 | icon: HomeOutlined, 12 | title: '首页', 13 | path: '/web/index', 14 | component: List 15 | }, 16 | { 17 | menu: true, 18 | icon: EditOutlined, 19 | title: '归档', 20 | path: '/web/achieve', 21 | component: Archive 22 | }, 23 | { 24 | menu: true, 25 | icon: StarOutlined, 26 | title: '收藏', 27 | path: '/web/star', 28 | component: Star 29 | }, 30 | { 31 | menu: true, 32 | icon: StarOutlined, 33 | title: '关于', 34 | path: '/web/about', 35 | component: About 36 | } 37 | ] 38 | 39 | export default webRoutes -------------------------------------------------------------------------------- /react-blog/src/api/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { message } from 'antd' 3 | 4 | //如果5s内没有请求回来数据则掐断 5 | axios.default.timeout = 5000 6 | 7 | // axios.default.baseUrl = 'http://xiangxi.red/api' 8 | 9 | // http request 拦截器 10 | axios.interceptors.request.use( 11 | config => { 12 | config.headers = { 13 | 14 | } 15 | return config 16 | }, 17 | error => { 18 | message.error('请求出错了,请稍后重试') 19 | return Promise.reject(error) 20 | } 21 | ) 22 | 23 | // http response 拦截器 24 | axios.interceptors.response.use( 25 | res => { 26 | return res 27 | }, 28 | error => { 29 | message.error('请求出错了,请稍后重试') 30 | return Promise.reject(error) 31 | } 32 | ) 33 | 34 | export default { 35 | get (url, params = {}) { 36 | return new Promise((resolve, reject) => { 37 | axios.get(url, { 38 | params 39 | }) 40 | .then(res =>{ 41 | resolve(res.data) 42 | }) 43 | }) 44 | }, 45 | post (url, data = {}) { 46 | return new Promise((resolve, reject) => { 47 | axios.get(url, data) 48 | .then(res =>{ 49 | resolve(res.data) 50 | }) 51 | }) 52 | } 53 | } -------------------------------------------------------------------------------- /react-blog/src/assets/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-blog/src/assets/img/avatar.jpg -------------------------------------------------------------------------------- /react-blog/src/assets/root.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0px; 3 | margin: 0px; 4 | } 5 | .mr10 { 6 | margin-right: 10px; 7 | } 8 | .mr20 { 9 | margin-right: 20px; 10 | } 11 | .mr30 { 12 | margin-right: 30px; 13 | } 14 | .ml10 { 15 | margin-left: 10px; 16 | } 17 | .ml20 { 18 | margin-left: 20px; 19 | } 20 | .ml30 { 21 | margin-left: 30px; 22 | } 23 | .mb10 { 24 | margin-bottom: 10px; 25 | } 26 | .mb20 { 27 | margin-bottom: 20px; 28 | } 29 | .mb30 { 30 | margin-bottom: 30px; 31 | } 32 | .mt10 { 33 | margin-top: 10px; 34 | } 35 | .mt20 { 36 | margin-top: 20px; 37 | } 38 | .mt30 { 39 | margin-top: 30px; 40 | } 41 | /* 42 | 重置样式 43 | */ -------------------------------------------------------------------------------- /react-blog/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react-blog/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import 'antd/dist/antd.css' 5 | import App from './App'; 6 | import * as serviceWorker from './serviceWorker'; 7 | 8 | ReactDOM.render(, document.getElementById('root')); 9 | 10 | // If you want your app to work offline and load faster, you can change 11 | // unregister() to register() below. Note this comes with some pitfalls. 12 | // Learn more about service workers: https://bit.ly/CRA-PWA 13 | serviceWorker.unregister(); 14 | -------------------------------------------------------------------------------- /react-blog/src/pages/admin/home/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | class Home extends Component { 4 | render () { 5 | return ( 6 |
    我是首页组件
    7 | ) 8 | } 9 | } 10 | export default Home -------------------------------------------------------------------------------- /react-blog/src/pages/admin/layout/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | class Layout extends Component { 4 | render () { 5 | return ( 6 |
    Hello Layout
    7 | ) 8 | } 9 | } 10 | export default Layout -------------------------------------------------------------------------------- /react-blog/src/pages/admin/login/index.less: -------------------------------------------------------------------------------- 1 | .login{ 2 | width: 99vw; 3 | height: 99vh; 4 | position: relative; 5 | &-form{ 6 | position: absolute; 7 | left: 50%; 8 | top: 50%; 9 | transform: translate(-50%,-100%); 10 | } 11 | } -------------------------------------------------------------------------------- /react-blog/src/pages/web/about/about.less: -------------------------------------------------------------------------------- 1 | .about { 2 | .about-list { 3 | &, 4 | ul { 5 | list-style: circle; 6 | margin-left: 20px; 7 | li { 8 | margin-top: 6px; 9 | } 10 | } 11 | } 12 | .icon-email { 13 | margin-right: 6px; 14 | vertical-align: middle; 15 | } 16 | @keyframes me { 17 | 0% { 18 | background: yellow; 19 | } 20 | 100% { 21 | background: pink; 22 | } 23 | } 24 | @-webkit-keyframes me { 25 | 0% { 26 | background: yellow; 27 | } 28 | 100% { 29 | background: pink; 30 | } 31 | } 32 | .code { 33 | width: 70px; 34 | position: relative; 35 | animation: me 3s infinite ease-in-out alternate; 36 | } 37 | .link { 38 | position: relative; 39 | text-decoration: none; 40 | color: #121314; 41 | &:after { 42 | content: ""; 43 | position: absolute; 44 | top: 60%; 45 | left: -0.1em; 46 | right: -0.1em; 47 | bottom: 0; 48 | transition: top 200ms cubic-bezier(0, .8, .13, 1); 49 | background-color: rgba(79,192,141,0.5); 50 | } 51 | &:hover:after { 52 | top: 0%; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /react-blog/src/pages/web/archive/index.less: -------------------------------------------------------------------------------- 1 | .ant-card-body{ 2 | padding: 24px; 3 | zoom: 1; 4 | } -------------------------------------------------------------------------------- /react-blog/src/pages/web/header/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Layout, Row, Col, Menu } from 'antd' 3 | import { Link } from 'react-router-dom' 4 | import { SmileTwoTone,HomeOutlined } from '@ant-design/icons'; 5 | import './index.less' 6 | import menus from '../../../Router/web' 7 | 8 | const { Header } = Layout 9 | 10 | class HeaderCustom extends Component { 11 | constructor(props) { 12 | super(props) 13 | this.state = { 14 | visible: false 15 | } 16 | } 17 | 18 | render () { 19 | const key = sessionStorage.getItem('webKey') || '0' 20 | 21 | //拿到menu为true字段的所有数据 22 | const list = menus.filter(v => v.menu) 23 | const menuList = list.map((item, i) => { 24 | return sessionStorage.setItem('webKey', String(i)) }> 25 | 26 | 27 | {item.title} 28 | 29 | 30 | }) 31 | return ( 32 |
    33 | 34 | 35 |
    36 | 37 | 旅梦博客开发 38 |
    39 | 40 | 41 | {/* 对应webkey 使其在刷新后仍能停留在选中页面 */} 42 | 43 | { menuList } 44 | 45 | 46 |
    47 |
    48 | ) 49 | } 50 | } 51 | 52 | export default HeaderCustom -------------------------------------------------------------------------------- /react-blog/src/pages/web/header/index.less: -------------------------------------------------------------------------------- 1 | .header-Container{ 2 | background-color: #fff; 3 | padding: 0; 4 | .logo{ 5 | width: 100%; 6 | height: 31px; 7 | line-height: 31px; 8 | margin: 16px 28px 16px 0; 9 | float: left; 10 | padding-left: 10px; 11 | } 12 | .ant-menu-horizontal{ 13 | height: 64px; 14 | line-height: 64px; 15 | display: flex; 16 | justify-content: space-around; 17 | border-bottom: none; 18 | } 19 | } -------------------------------------------------------------------------------- /react-blog/src/pages/web/layout/index.less: -------------------------------------------------------------------------------- 1 | .wrapper{ 2 | height: 100%; 3 | .wrapper-container{ 4 | height: 100%; 5 | .wrapper-content{ 6 | height: 100%; 7 | &::-webkit-scrollbar{ 8 | display: none; 9 | } 10 | } 11 | } 12 | .ant-layout-footer{ 13 | text-align: center; 14 | } 15 | } -------------------------------------------------------------------------------- /react-blog/src/pages/web/list/list.less: -------------------------------------------------------------------------------- 1 | .list-wrapper .ant-list-item { 2 | background: #fff; 3 | padding: 20px; 4 | margin-bottom: 10px; 5 | } 6 | .ant-list-item .ant-list-item-meta-title { 7 | font-size: 1.2rem; 8 | line-height: 1.2; 9 | /* color: #2e3135; */ 10 | } 11 | .read-all { 12 | display: flex; 13 | flex-direction: row-reverse; 14 | } 15 | .list-item { 16 | cursor: pointer; 17 | } 18 | .list-wrapper .ant-list-vertical .ant-list-item-action>li { 19 | padding: 0 8px; 20 | } 21 | .ant-list-item{ 22 | display: block; 23 | } 24 | .ant-list-item-action{ 25 | margin-left: 0; 26 | margin-top: 24px; 27 | } 28 | .ant-list-item-meta-title{ 29 | margin-bottom: 15px; 30 | } -------------------------------------------------------------------------------- /react-blog/src/pages/web/sider/index.less: -------------------------------------------------------------------------------- 1 | .ant-card-body { 2 | padding: 0; 3 | } 4 | .sider-container 5 | .recent-list { 6 | width: 100%; 7 | } 8 | .sider-container 9 | .recent-list li { 10 | display: block; 11 | padding: 5px 24px; 12 | cursor: pointer; 13 | font-size: 14px; 14 | line-height: 32px; 15 | color: #8590a6; 16 | text-align: left; 17 | } 18 | .sider-container 19 | .recent-list { 20 | padding: 0; 21 | li:hover { 22 | color: rgb(0, 132, 255); 23 | background: rgb(246, 246, 246); 24 | } 25 | } 26 | 27 | .admin-info{ 28 | background: #fff; 29 | margin-bottom: 20px; 30 | header{ 31 | text-align: center; 32 | padding: 15px 0 0 0; 33 | img{ 34 | width: 150px; 35 | height: 150px; 36 | max-width: 100%; 37 | border-radius: 50%; 38 | transition: transform 2s ease-out; 39 | &:hover{ 40 | transform: rotateZ(360deg); 41 | } 42 | } 43 | } 44 | } 45 | 46 | .admin-name { 47 | text-align: center; 48 | font-weight: bold; 49 | padding: 8px 0 0; 50 | font-size: 1.5em; 51 | font-family: "Monospace Number", "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; 52 | } 53 | .admin-desc { 54 | text-align: center; 55 | padding: 10px 15px 20px 15px; 56 | font-size: 14px; 57 | } 58 | .tags-wrapper { 59 | margin-top: 20px; 60 | .tags-content { 61 | padding: 0 20px 20px; 62 | } 63 | } 64 | 65 | .tags-content { 66 | padding: 20px; 67 | } 68 | .tags-content .ant-tag { 69 | margin: 6px; 70 | } -------------------------------------------------------------------------------- /react-blog/src/pages/web/star/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { List } from 'antd' 3 | import './star.less' 4 | 5 | class Collect extends Component { 6 | constructor(props) { 7 | super (props) 8 | this.state = { 9 | "data": [ 10 | { 11 | "createdAt": "2019-04-10 10:19", 12 | "updatedAt": "2019-04-10 10:19", 13 | "id": 3, 14 | "title": "React 16 加载性能优化指南", 15 | "url": "https://juejin.im/post/5b506ae0e51d45191a0d4ec9" 16 | }, 17 | { 18 | "createdAt": "2019-03-30 14:02", 19 | "updatedAt": "2019-03-30 14:02", 20 | "id": 2, 21 | "title": "CentOS7 系统目录详解和常用命令[文件和目录]", 22 | "url": "https://blog.csdn.net/qq_22860341/article/details/81363655" 23 | } 24 | ], 25 | "total": 2, 26 | "code": 1000, 27 | "desc": "success" 28 | } 29 | } 30 | render () { 31 | const pagination = { 32 | pageSize: 10, 33 | size: 'small', 34 | current: 1, 35 | total: 2, 36 | 37 | } 38 | return ( 39 | 文章收藏} 43 | dataSource = {this.state.data} 44 | pagination={this.state.data.length ? pagination : null} 45 | renderItem = {item => ( 46 | 47 | {item.title}]}> 48 | 49 | )} 50 | > 51 | 52 | 53 | ) 54 | } 55 | } 56 | 57 | export default Collect -------------------------------------------------------------------------------- /react-blog/src/pages/web/star/star.less: -------------------------------------------------------------------------------- 1 | .star-header { 2 | color: #000; 3 | font-size: 1.2em; 4 | } 5 | .star-list { 6 | background: #fff; 7 | padding: 0px 30px 20px 30px; 8 | } 9 | 10 | .star-list .ant-list-item-meta-description { 11 | color: black; 12 | } 13 | 14 | .star-list .ant-list-item { 15 | padding-bottom: 0; 16 | } 17 | 18 | .star-list .article-author { 19 | margin-left: 20px; 20 | } -------------------------------------------------------------------------------- /react-blog/src/requireLogin.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default function requireLogin (Component) { 4 | // 组件有已经登录的模块, 直接返回(防止重新渲染) 5 | if (Component.requireLogin) { 6 | return Component.requireLogin 7 | } 8 | 9 | // 创建验证组件 10 | class requireLogin extends Component { 11 | constructor (props) { 12 | super(props) 13 | this.state = { 14 | login: true 15 | } 16 | } 17 | 18 | //组件挂载的时候判断 19 | componentWillMount() { 20 | this.checkAuth() 21 | } 22 | 23 | //退出登录 24 | componentWillReceiveProps () { 25 | this.checkAuth() 26 | } 27 | 28 | 29 | checkAuth () { 30 | // 判断登录 31 | const login = sessionStorage.getItem('blogUser') 32 | // 未登录, 重定向去到登录页面 33 | const pathname = this.props.location.pathname !== '/login' 34 | if( !login && pathname ){ 35 | this.props.history.push('/login') 36 | return 37 | } 38 | } 39 | render() { 40 | if (this.state.login) { 41 | return 42 | } 43 | return '' 44 | } 45 | } 46 | 47 | Component.requireLogin = requireLogin 48 | 49 | return Component.requireLogin 50 | } -------------------------------------------------------------------------------- /react-blog/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /react-blog/src/utils(公共方法)/index.js: -------------------------------------------------------------------------------- 1 | export const color = [ 2 | 'magenta', 3 | 'red', 4 | 'volcano', 5 | 'orange', 6 | 'gold', 7 | 'lime', 8 | 'green', 9 | 'cyan', 10 | 'blue', 11 | 'geekblue', 12 | 'purple' 13 | ] -------------------------------------------------------------------------------- /react-blog/src/utils(公共方法)/loadable.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Loadable from 'react-loadable' 3 | import { Spin } from 'antd' 4 | 5 | const loadingComponet = ({ isLoading, error }) => { 6 | // Handle the loading state 7 | if (isLoading) { 8 | return
    ; 9 | } 10 | // Handle the error state 11 | else if (error) { 12 | return
    Sorry, there was a problem loading the page.
    ; 13 | } 14 | else { 15 | return null; 16 | } 17 | }; 18 | 19 | export default (loader, loading = loadingComponet) => { 20 | return Loadable({ 21 | loader, 22 | loading 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /react-comment/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-comment/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-comment", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-scripts": "3.3.0" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "build": "react-scripts build", 16 | "test": "react-scripts test", 17 | "eject": "react-scripts eject" 18 | }, 19 | "eslintConfig": { 20 | "extends": "react-app" 21 | }, 22 | "browserslist": { 23 | "production": [ 24 | ">0.2%", 25 | "not dead", 26 | "not op_mini all" 27 | ], 28 | "development": [ 29 | "last 1 chrome version", 30 | "last 1 firefox version", 31 | "last 1 safari version" 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /react-comment/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-comment/public/favicon.ico -------------------------------------------------------------------------------- /react-comment/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-comment/public/logo192.png -------------------------------------------------------------------------------- /react-comment/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-comment/public/logo512.png -------------------------------------------------------------------------------- /react-comment/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-comment/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /react-comment/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-comment/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // import logo from './logo.svg'; 3 | import './App.css'; 4 | import CommentInput from './CommentInput' 5 | 6 | class App extends React.Component { 7 | // 静态属性 8 | state = { 9 | commentList: [ 10 | 11 | ] 12 | } 13 | onPublish = (userName, comment) => { 14 | // console.log(userName, comment); 15 | let c = {userName,comment} 16 | //不可变数据 17 | //指向同一个对象 18 | // let obj = {}; let obj1 = obj; obj1.name = 'li' 19 | // let obj1= Object.assign({}, obj) 20 | let list = this.state.commentList.slice(0); 21 | list.push(c) 22 | console.log(list) 23 | // this.state.commentList = list 24 | this.setState({ 25 | commentList: list 26 | }) 27 | } 28 | handleDel = (event) => { 29 | // del i ? 30 | // data-i 31 | 32 | const i = parseInt(event.target.dataset.i) 33 | const list = this.state.commentList.slice(0) 34 | list.splice(i,1); 35 | this.setState({ 36 | commentList: list 37 | }) 38 | } 39 | render() { 40 | return ( 41 | <> 42 | 43 | { this.state.commentList.length } 44 | {/* */} 45 | { 46 | this.state.commentList && this.state.commentList.map( 47 | (c, i) => { 48 | return ( 49 |
  • 50 | {c.userName}: {c.comment} 51 | 52 |
  • 53 | ) 54 | } 55 | ) 56 | } 57 | 58 | ) 59 | } 60 | } 61 | 62 | export default App; 63 | -------------------------------------------------------------------------------- /react-comment/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-comment/src/CommentInput.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | class CommentInput extends React.Component{ 4 | 5 | handlePublish = () => { 6 | const userName = this.refs.userName.value; 7 | const comment = this.refs.comment.value; 8 | // 通知父组件 存在数组里面 9 | const { onPublish } = this.props; 10 | onPublish(userName, comment) 11 | } 12 | render() { 13 | return ( 14 | <> 15 | 用户名: 16 | 评论内容: 17 | 18 | 19 | ) 20 | } 21 | } 22 | export default CommentInput; -------------------------------------------------------------------------------- /react-comment/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react-comment/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /react-comment/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /react-demo/LifeCycle.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | class LifeCycle extends Component { 4 | constructor (props) { 5 | super(props) 6 | console.log('1. 构造函数') 7 | this.state = { 8 | msg: '来自属性传递' + props.prop 9 | } 10 | } 11 | componentWillMount () { 12 | // 此时可以访问属性和状态,可以进行api调用 但是没有办法做dom相关操作 13 | // console.log(this.state.msg) 14 | console.log('2. 组件将要挂载') 15 | } 16 | componentDidMount () { 17 | // 组件已经渲染完成, 可以进行状态更新操作 18 | console.log('3. 组件已挂载') 19 | } 20 | componentWillReceiveProps () { 21 | // 父组件传递的属性有变化, 做相应的操作 22 | console.log('4. 组件属性更新了') 23 | } 24 | shouldComponentUpdate () { 25 | // 组件是否需要更新, 返回boolean 26 | console.log('5. 组件是否需要更新?') 27 | return true 28 | } 29 | componentWillUpdate () { 30 | console.log('6. 组件将要更新') 31 | } 32 | componentDidUpdate () { 33 | console.log('7. 组件已经更新') 34 | } 35 | render () { 36 | console.log('组件渲染') 37 | return ( 38 |
    组件生命周期探究
    39 | ) 40 | } 41 | } 42 | 43 | export default class extends Component { 44 | constructor(props){ 45 | super(props) 46 | this.state = { 47 | someProp: '北辰' 48 | } 49 | 50 | setTimeout (() => { 51 | this.setState({ 52 | someProp: 'beichen' 53 | }) 54 | }, 2000) 55 | } 56 | render () { 57 | return 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /react-demo/demo1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 21 | 22 | -------------------------------------------------------------------------------- /react-demo/demo10/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 53 | 54 | -------------------------------------------------------------------------------- /react-demo/demo11/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Document 12 | 13 | 14 |
    15 | 16 | 51 | 52 | -------------------------------------------------------------------------------- /react-demo/demo2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 28 | 29 | -------------------------------------------------------------------------------- /react-demo/demo3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 29 | 30 | -------------------------------------------------------------------------------- /react-demo/demo4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 29 | 30 | -------------------------------------------------------------------------------- /react-demo/demo5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 16 | 17 | 18 | 50 | 51 | -------------------------------------------------------------------------------- /react-demo/demo6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Document 12 | 13 | 14 |
    15 | 16 | 17 | 40 | 41 | -------------------------------------------------------------------------------- /react-demo/demo7/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 43 | 44 | -------------------------------------------------------------------------------- /react-demo/demo8/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 |
    16 | 17 | 50 | 51 | -------------------------------------------------------------------------------- /react-demo/demo9(实现节流)/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Document 11 | 12 | 13 |
    14 | 15 | 16 | 52 | 53 | -------------------------------------------------------------------------------- /react-hoc/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-hoc/README.md: -------------------------------------------------------------------------------- 1 | # HOC 2 | higher order Component 3 | 4 | # 组件 5 | 是对 公共 html css state 的一个抽象 6 | 7 | # 高阶组件 8 | 是对 各个组件中 公共逻辑的一个抽象 9 | 1. 防止重复的代码 (页面复用) 降低代码的耦合度 10 | 2. 条件渲染 控制组件的渲染逻辑 (渲染劫持) 11 | 3. 捕获|劫持被处理的生命周期 12 | 13 | -------------------------------------------------------------------------------- /react-hoc/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /react-hoc/config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFilename = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFilename}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /react-hoc/config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /react-hoc/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-hoc/public/favicon.ico -------------------------------------------------------------------------------- /react-hoc/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-hoc/public/logo192.png -------------------------------------------------------------------------------- /react-hoc/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-hoc/public/logo512.png -------------------------------------------------------------------------------- /react-hoc/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-hoc/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-hoc/scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | 19 | const jest = require('jest'); 20 | const execSync = require('child_process').execSync; 21 | let argv = process.argv.slice(2); 22 | 23 | function isInGitRepository() { 24 | try { 25 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 26 | return true; 27 | } catch (e) { 28 | return false; 29 | } 30 | } 31 | 32 | function isInMercurialRepository() { 33 | try { 34 | execSync('hg --cwd . root', { stdio: 'ignore' }); 35 | return true; 36 | } catch (e) { 37 | return false; 38 | } 39 | } 40 | 41 | // Watch unless on CI or explicitly running all tests 42 | if ( 43 | !process.env.CI && 44 | argv.indexOf('--watchAll') === -1 && 45 | argv.indexOf('--watchAll=false') === -1 46 | ) { 47 | // https://github.com/facebook/create-react-app/issues/5210 48 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 49 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 50 | } 51 | 52 | 53 | jest.run(argv); 54 | -------------------------------------------------------------------------------- /react-hoc/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-hoc/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App() { 6 | return ( 7 |
    8 |
    9 | logo 10 |

    11 | Edit src/App.js and save to reload. 12 |

    13 | 19 | Learn React 20 | 21 |
    22 |
    23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /react-hoc/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-hoc/src/component/example1/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const withMosu = (Component) => { 4 | return class extends React.Component { 5 | state = { x: 0, y: 0} 6 | handleMouseMove = (event) => { 7 | this.setState({ 8 | x: event.clientX, 9 | y: event.clientY 10 | }) 11 | console.log(event) 12 | } 13 | render () { 14 | return ( 15 |
    16 | 17 |
    18 | ) 19 | } 20 | } 21 | } 22 | 23 | // 定义一个纯函数无状态的组件 24 | const App = (props) => { 25 | const { x, y } = props.mouse 26 | return ( 27 |
    28 |

    The mouse position is ({x}, {y})

    29 |
    30 | ) 31 | } 32 | 33 | // const test = () => { 34 | // return ( 35 | //
    {x}, {y}
    36 | // ) 37 | // } 38 | 39 | const AppWithMouse = withMosu(App) // 高阶组件替组件干活 40 | 41 | export default AppWithMouse -------------------------------------------------------------------------------- /react-hoc/src/component/example2/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | // HOC 高阶组件 4 | 5 | function HOC( WrappedComponent ) { 6 | return class extends Component { 7 | constructor (props) { 8 | super(props) 9 | this.state = { 10 | name: '' 11 | } 12 | } 13 | onChange = ( event ) => { 14 | // this.setState 在这里!!!是异步的 15 | this.setState({ 16 | name: event.target.value 17 | }) 18 | console.log(this.state.name) 19 | } 20 | 21 | render () { 22 | const newProps = { 23 | name: { 24 | value: this.state.name, 25 | onChange: this.onChange 26 | } 27 | } 28 | return 29 | } 30 | } 31 | } 32 | 33 | // 使用 34 | @HOC 35 | class Example extends Component { 36 | render () { 37 | return ( 38 | 39 | ) 40 | } 41 | } 42 | 43 | // const Example = HOC(Example) 44 | export default Example -------------------------------------------------------------------------------- /react-hoc/src/component/example3/OperateRefsHOC.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function HOC (WrappedComponent) { 4 | let inputElement = null 5 | 6 | function handleClick() { 7 | inputElement.focus() 8 | } 9 | 10 | return ( props ) => ( 11 |
    12 | {inputElement = el}}/> 13 | 14 |
    15 | ) 16 | } 17 | 18 | export default HOC -------------------------------------------------------------------------------- /react-hoc/src/component/example3/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import User from './user' 3 | import HOC from './OperateRefsHOC' 4 | 5 | const EnhanceUser = HOC(User) 6 | 7 | class OperateRefs extends React.Component { 8 | render () { 9 | return 10 | } 11 | } 12 | 13 | export default OperateRefs -------------------------------------------------------------------------------- /react-hoc/src/component/example3/user.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | 4 | class User extends React.Component { 5 | inputElement = null 6 | 7 | sayHello () { 8 | console.log('hello world') 9 | } 10 | 11 | constructor(props) { 12 | super(props) 13 | this.focus = this.focus.bind(this) 14 | this.onChaneg = this.focus.bind(this) 15 | } 16 | 17 | state = { 18 | name: '', 19 | age: 0 20 | } 21 | 22 | focus () { 23 | this.inputElement.focus() 24 | } 25 | 26 | onChange = (e) => { 27 | this.setState({ 28 | age: e.target.value 29 | }) 30 | } 31 | 32 | componentDidMount() { 33 | this.setState({ 34 | name: this.props.name, 35 | age: this.props.age 36 | }) 37 | } 38 | 39 | render () { 40 | return ( 41 |
    42 |
    姓名: {this.state.name}
    43 |
    44 | 年龄: 45 | { 48 | if (this.props.inputRef) { 49 | this.props.inputRef(input) // 父组件传入的ref回调函数 50 | } 51 | this.inputElement = input 52 | }}> 53 | 54 | 55 |
    56 | 57 |
    58 | 59 |
    60 |
    61 | ) 62 | } 63 | } 64 | 65 | export default User -------------------------------------------------------------------------------- /react-hoc/src/component/useRef/Use.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useRef } from 'react' 2 | 3 | function Example () { 4 | const inputEl = useRef(null) 5 | 6 | const onButtonClick = () => { 7 | inputEl.current.value = '猛哥aaaa' 8 | console.log(inputEl) 9 | } 10 | 11 | const [text, setText] = useState('猛哥') 12 | const textRef = useRef() 13 | 14 | // 初次渲染执行 15 | useEffect(() => { 16 | textRef.current = text 17 | console.log(textRef.current) 18 | }) 19 | 20 | return ( 21 |
    22 | 23 | 24 |
    25 | {setText(e.target.value)}}> 26 |
    27 | ) 28 | } 29 | 30 | export default Example -------------------------------------------------------------------------------- /react-hoc/src/component/useRef/index.js: -------------------------------------------------------------------------------- 1 | // useRef 获取DOM元素 2 | // useRef 保存普通变量 3 | import React, { useRef } from 'react' 4 | 5 | function Example () { 6 | // inputEl这个变量是useRef函数的返回值,那么这个变量给谁当ref属性,就能表示该元素的DOM 7 | const inputEl = useRef(null) 8 | 9 | const onButtonClick = () =>{ 10 | inputEl.current.value = '猛哥贼帅' 11 | console.log(inputEl) 12 | } 13 | 14 | return ( 15 |
    16 | 17 | 18 |
    19 | ) 20 | } 21 | 22 | export default Example 23 | -------------------------------------------------------------------------------- /react-hoc/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react-hoc/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './component/example2'; 5 | import Example3 from './component/example3'; 6 | import * as serviceWorker from './serviceWorker'; 7 | import Demo6 from './component/useRef' 8 | import AnotherDemo6 from './component/useRef/Use' 9 | // ReactDOM.render(, document.getElementById('root')); 10 | // ReactDOM.render(, document.getElementById('root')); 11 | ReactDOM.render(, document.getElementById('root')); 12 | // If you want your app to work offline and load faster, you can change 13 | // unregister() to register() below. Note this comes with some pitfalls. 14 | // Learn more about service workers: https://bit.ly/CRA-PWA 15 | serviceWorker.unregister(); 16 | -------------------------------------------------------------------------------- /react-hoc/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /react-hook/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-hook/README.md: -------------------------------------------------------------------------------- 1 | - hooks 本质上就是一类特殊的函数 目的就是让你不再写 class, 让function一统江湖 2 | # useState 就是一个hook 3 | import React, { useState } from 'react'; 4 | 5 | function Example() { 6 | // 声明一个新的叫做 “count” 的 state 变量 7 | const [count, setCount] = useState(0); 8 | 9 | return ( 10 |
    11 |

    You clicked {count} times

    12 | 15 |
    16 | ); 17 | 18 | # react 是如何保证useState找到自己对应的state 19 | 1. 是根据useState出现的顺序来确定的 20 | 2. React hooks 不能出现再条件判断语句中, 因为他必须有完全一样的渲染顺序 21 | 22 | # componentWillUpdate 23 | 数据源更改时执行该生命周期 24 | 是再setState执行时,数据源更改之前执行 25 | 26 | ## useEffect 27 | 1. React 首次渲染和之后的每一次渲染都会调用useEffect 28 | 2. useEffect里面定义的函数是异步执行的,他不会阻碍浏览器更新视图 29 | 30 | ## useContext 31 | **使父子组件的传值变得更加简单** 32 | 33 | ## useMemo 34 | 优化Hooks一些缺陷 35 | -------------------------------------------------------------------------------- /react-hook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-hook", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "antd": "^4.2.0", 10 | "core-js": "^2.6.11", 11 | "react": "^16.13.0", 12 | "react-dom": "^16.13.0", 13 | "react-router-dom": "^5.1.2", 14 | "react-scripts": "3.4.0", 15 | "recharts": "^1.8.5" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": "react-app" 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-hook/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-hook/public/favicon.ico -------------------------------------------------------------------------------- /react-hook/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-hook/public/logo192.png -------------------------------------------------------------------------------- /react-hook/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-hook/public/logo512.png -------------------------------------------------------------------------------- /react-hook/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-hook/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-hook/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | width: 1200px; 3 | margin: auto; 4 | text-align: center; 5 | } 6 | body{ 7 | text-align: center; 8 | } 9 | 10 | .history-group { 11 | display: flex; 12 | justify-content: center; 13 | width: 1200px; 14 | margin: auto; 15 | } 16 | 17 | table, 18 | th, 19 | td { 20 | border: 1px solid #ccc; 21 | border-collapse: collapse; 22 | } 23 | 24 | th, 25 | td { 26 | padding: 5px; 27 | text-align: left; 28 | } 29 | 30 | .global-stats > table { 31 | margin: auto; 32 | margin-top: 0.5rem; 33 | margin-bottom: 1rem; 34 | } -------------------------------------------------------------------------------- /react-hook/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | // import axios from 'axios' 5 | import GlobalStats from './component/useEffect/demo' 6 | import CountriesChart from './component/useEffect/CountriesChart' 7 | import SelectDataKey from './component/useEffect/SelectDataKey' 8 | const BASE_URL = "https://corona.lmao.ninja"; 9 | function App() { 10 | const [globalStats, setGlobalStats] = useState({}); 11 | const [countries, setCountries] = useState([]) 12 | const [key, setKey] = useState('cases') 13 | // useEffect(() => { 14 | // axios.get(`${BASE_URL}/v2/all`).then((res) => { 15 | // console.log(res) 16 | // setGlobalStats(res.data) 17 | // }) 18 | // }, []) 19 | useEffect(() => { 20 | const fetchGlobalStats = async () => { 21 | const response = await fetch(`${BASE_URL}/v2/all`); 22 | const data = await response.json(); 23 | console.log(data) 24 | setGlobalStats(data); 25 | }; 26 | 27 | fetchGlobalStats(); 28 | const intervalId = setInterval(fetchGlobalStats, 10000); 29 | 30 | return () => clearInterval(intervalId); 31 | }, []) 32 | 33 | useEffect(() => { 34 | const fetchCountries = async () => { 35 | const response = await fetch(`${BASE_URL}/v2/countries?sort=${key}`); 36 | const data = await response.json(); 37 | console.log(data) 38 | setCountries(data.slice(0, 10)); 39 | }; 40 | fetchCountries() 41 | }, [key]) 42 | 43 | return ( 44 |
    45 |

    新型冠状病毒

    46 | 47 | setKey(e.target.value)} /> 48 | 49 |
    50 | ) 51 | } 52 | 53 | export default App; 54 | -------------------------------------------------------------------------------- /react-hook/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-hook/src/component/useEffect/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | class Example extends Component { 4 | constructor(props) { 5 | super(props) 6 | this.state = { 7 | count: [0] 8 | } 9 | } 10 | 11 | // 组件初次渲染执行 12 | componentDidMount() { 13 | console.log(`你点击了 ${this.state.count}次`) 14 | this.setState({ 15 | count:[0,1] 16 | },() => { 17 | console.log(this.state.count) 18 | setTimeout(() => { 19 | var a = this.state.count 20 | a.push(2) 21 | this.setState({ 22 | count:a 23 | },() => { 24 | console.log(this.state.count) 25 | }) 26 | }, 30000); 27 | }) 28 | } 29 | 30 | componentDidUpdate () { 31 | console.log(`你点击了 ${this.state.count}次`) 32 | } 33 | 34 | shouldComponentUpdate(){ 35 | return true 36 | } 37 | 38 | addCount () { 39 | this.setState({ 40 | count: this.state.count + 1 41 | }) 42 | } 43 | 44 | render () { 45 | return ( 46 |
    47 |

    你点了{this.state.count}次

    48 | 49 |
    50 | ) 51 | } 52 | } 53 | 54 | export default Example -------------------------------------------------------------------------------- /react-hook/src/component/useEffect/indexHook.js: -------------------------------------------------------------------------------- 1 | // 副作用 -- hooks模式下状态 {state} 发生变更的时候提供给我们做额外操作的地方 2 | import React, { useState, useEffect } from 'react' 3 | function Example () { 4 | const [ count, setCount ] = useState(0) 5 | 6 | // 不需要考虑时间刻度 7 | // 首次渲染和每一次渲染都会执行 8 | useEffect(() => { 9 | console.log(`你点击了 ${count}次`) 10 | // axios.get('http://musicapi.leanapp.cn/comment/music?id=186016&limit=1').then( 11 | // (res) => { 12 | // const data = res.data 13 | // console.log(data) 14 | // } 15 | // ) 16 | }) 17 | 18 | return ( 19 |
    20 |

    你点了{count}次

    21 | 22 |
    23 | ) 24 | } 25 | 26 | export default Example 27 | 28 | -------------------------------------------------------------------------------- /react-hook/src/component/useEffect/makeUnmount.js: -------------------------------------------------------------------------------- 1 | // componentWillUnmount 组件卸载之前 2 | // useEffect 实现组件componentWillUnmount (解绑副作用) 3 | 4 | import { BrowserRouter as Router, Route, Link } from 'react-router-dom' 5 | // 副作用 -- hooks模式下状态 {state} 发生变更的时候提供给我们做额外操作的地方 6 | import React, { useState, useEffect } from 'react' 7 | function Example () { 8 | const [ count, setCount ] = useState(0) 9 | 10 | // 不需要考虑时间刻度 11 | // 首次渲染和每一次渲染都会执行 12 | useEffect(() => { 13 | console.log(`你点击了 ${count}次`) 14 | 15 | return () => { 16 | console.log('-----------------你离开了页面,组件卸载') 17 | } 18 | },[]) 19 | 20 | return ( 21 |
    22 |

    你点了{count}次

    23 | 24 | 25 | 26 |
      27 |
    • 首页
    • 28 |
    • 29 | 列表 30 |
    • 31 | 32 | 33 |
    34 |
    35 |
    36 | ) 37 | } 38 | 39 | function Index () { 40 | useEffect(() => { 41 | console.log('useEffect => 这里是Index页面') 42 | return () => { 43 | console.log('你离开了Index页面') 44 | } 45 | }, []) 46 | return

    React Hooks

    47 | } 48 | 49 | function List () { 50 | useEffect(() => { 51 | console.log('useEffect => 这里是List页面') 52 | }, [])//[] 组件被销毁的时候进行解绑 53 | return

    List-Page

    54 | } 55 | 56 | export default Example 57 | 58 | -------------------------------------------------------------------------------- /react-hook/src/component/useState/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | class Example extends Component { 4 | constructor(props) { 5 | super(props) 6 | this.state = { 7 | count: 0 8 | } 9 | } 10 | 11 | addCount () { 12 | this.setState({ 13 | count: this.state.count + 1 14 | }) 15 | } 16 | 17 | render () { 18 | return ( 19 |
    20 |

    你点了{this.state.count}次

    21 | 22 |
    23 | ) 24 | } 25 | } 26 | 27 | export default Example -------------------------------------------------------------------------------- /react-hook/src/component/useState/indexHook.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | // useState 就是一个hook 3 | 4 | function Example () { 5 | const [ count, setCount ] = useState(0) 6 | 7 | // let _useState = useState(0) 8 | // let count = _useState[0] 9 | // let setCount = _useState[1] 10 | 11 | // setCount == this.setState({ count : 'number'}) 12 | return ( 13 |
    14 |

    你点了{count}次

    15 | 16 |
    17 | ) 18 | } 19 | 20 | // let showSex = true 21 | // function Example2 () { 22 | // // const [ count, name, age, setCount, setName, setAge ] = useState(0, "蜗牛", 18) 23 | // const [ age, setAge ] = useState(18) 24 | // if(showSex){ 25 | // const [ sex, setSex ] = useState('男') 26 | // showSex = false 27 | // } 28 | 29 | // const [ work, setWork ] = useState('前端程序员') 30 | 31 | // // react 是如何保证useState找到自己对应的state 32 | // // react 是根据useState出现的顺序来确定的 33 | 34 | // return ( 35 | //
    36 | //

    setAge( age+ 1)}>江军 今年: {age}岁

    37 | //

    性别: {sex}

    38 | //

    工作是: {work}

    39 | //
    40 | // ) 41 | // } 42 | 43 | export default Example 44 | 45 | // hooks 本质上就是一类特殊的函数 目的就是让你不再写 class, 让function一统江湖 -------------------------------------------------------------------------------- /react-hook/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 5 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | code { 12 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 13 | monospace; 14 | } 15 | -------------------------------------------------------------------------------- /react-hook/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /react-jianshu/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-jianshu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "axios": "^0.19.2", 10 | "immutable": "^4.0.0-rc.12", 11 | "react": "^16.13.0", 12 | "react-dom": "^16.13.0", 13 | "react-loadable": "^5.5.0", 14 | "react-redux": "^7.2.0", 15 | "react-router-dom": "^5.1.2", 16 | "react-scripts": "3.4.0", 17 | "react-transition-group": "^4.3.0", 18 | "redux": "^4.0.5", 19 | "redux-thunk": "^2.3.0", 20 | "styled-components": "^5.0.1" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": "react-app" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /react-jianshu/public/api/detail.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true, 3 | "data": { 4 | "title": "Redux中间件之redux-thunk使用详解", 5 | "content":"

    Redux的核心概念其实很简单:将需要修改的state都存入到store里,发起一个action用来描述发生了什么,用reducers描述action如何改变state tree 。创建store的时候需要传入reducer,真正能改变store中数据的是store.dispatch API。

    dispatch一个action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware。你可以利用 Redux middleware 来进行日志记录、创建崩溃报告、调用异步接口或者路由等等。换言之,中间件都是对store.dispatch()的增强

    " 6 | } 7 | } -------------------------------------------------------------------------------- /react-jianshu/public/api/homeList.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true, 3 | "data": [ 4 | { 5 | "id": 5, 6 | "title": "我看到了妻子的另一面", 7 | "desc": "父母永远都是孩子最亲近的人,特别是妈妈从怀孕到生孩子这个过程,她们给了孩子生命,同时也时刻守护着孩子们的成长。 绝大多数情况下,妈妈和孩子都是最...", 8 | "imgUrl": "https://upload-images.jianshu.io/upload_images/14805474-d0c2e5243e2c9d41.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240" 9 | }, 10 | { 11 | "id": 6, 12 | "title": "一个人是否值得交往,看这四点就够了", 13 | "desc": "有人说:“不必把太多人请进生命里,若他们走进不了你的内心,就只会把你的生命搅扰得拥挤不堪。” 朋友不必多,贵在能知心。珍贵的情谊,要留给最值得结...", 14 | "imgUrl": "https://upload-images.jianshu.io/upload_images/14805474-d0c2e5243e2c9d41.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240" 15 | }, 16 | { 17 | "id": 7, 18 | "title": "“因为10个口罩,我看到了妻子的另一面,终止了两年的婚外恋”", 19 | "desc": "01 作家詹迪·尼尔森曾说:“遇见灵魂伴侣的感觉,就好像是走进一座你曾经住过的房子里——你认识那些家具,认识墙上的画,架上的书,抽屉里的东西:如...", 20 | "imgUrl": "https://upload-images.jianshu.io/upload_images/14805474-d0c2e5243e2c9d41.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240" 21 | }, 22 | { 23 | "id": 8, 24 | "title": "“因为10个口罩,我看到了妻子的另一面,终止了两年的婚外恋”", 25 | "desc": "01 作家詹迪·尼尔森曾说:“遇见灵魂伴侣的感觉,就好像是走进一座你曾经住过的房子里——你认识那些家具,认识墙上的画,架上的书,抽屉里的东西:如...", 26 | "imgUrl": "https://upload-images.jianshu.io/upload_images/14805474-d0c2e5243e2c9d41.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /react-jianshu/public/api/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true, 3 | "data": true 4 | } -------------------------------------------------------------------------------- /react-jianshu/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/public/favicon.ico -------------------------------------------------------------------------------- /react-jianshu/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/public/logo192.png -------------------------------------------------------------------------------- /react-jianshu/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/public/logo512.png -------------------------------------------------------------------------------- /react-jianshu/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-jianshu/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-jianshu/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './common/header' 3 | import store from './store' 4 | import { Provider } from 'react-redux' 5 | import { BrowserRouter, Route } from 'react-router-dom' 6 | import Home from './pages/home' 7 | import Detail from './pages/detail/loadable' 8 | import Login from './pages/login' 9 | import Write from './pages/write' 10 | 11 | function App() { 12 | return ( 13 | 14 | 15 | 16 |
    17 | {/* 内容都受BrowserHistory控制 */} 18 |
    19 | 20 | {/* ?不影响路由匹配 */} 21 | {/* 与List.js组件Link匹配 */} 22 | 23 | {/* */} 24 | 25 | 26 |
    27 | 28 | 29 | ); 30 | } 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /react-jianshu/src/common/header/store/actionCreator.js: -------------------------------------------------------------------------------- 1 | import * as types from './actionTypes' 2 | export const searchFocus = () => ({ 3 | type : types.SEARCH_FOCUS 4 | }) 5 | 6 | export const searchBlur = () => ({ 7 | type : types.SEARCH_BLUR 8 | }) -------------------------------------------------------------------------------- /react-jianshu/src/common/header/store/actionTypes.js: -------------------------------------------------------------------------------- 1 | export const SEARCH_FOCUS = 'search_focus' 2 | export const SEARCH_BLUR = 'search_blur' -------------------------------------------------------------------------------- /react-jianshu/src/common/header/store/index.js: -------------------------------------------------------------------------------- 1 | import reducer from './reducer' 2 | import * as actionCreator from './actionCreator' 3 | import * as actionTypes from './actionTypes' 4 | 5 | export { reducer,actionCreator,actionTypes } -------------------------------------------------------------------------------- /react-jianshu/src/common/header/store/reducer.js: -------------------------------------------------------------------------------- 1 | import * as types from './actionTypes' 2 | import { fromJS } from 'immutable' 3 | 4 | const defaultState = fromJS({ 5 | focused: false 6 | }); 7 | 8 | export default (state = defaultState, action) => { 9 | switch(action.type){ 10 | case types.SEARCH_FOCUS: 11 | // immutable对象的set方法,会结合之前immutable对象的值和设置的值,返回一个全新的对象 12 | return state.set('focused', true) 13 | // return { 14 | // focused: true 15 | // }; 16 | case types.SEARCH_BLUR: 17 | return state.set('focused', false) 18 | // return { 19 | // focused: false 20 | // }; 21 | 22 | // if(action.type === 'search_focus'){ 23 | // return { 24 | // focused: true 25 | // } 26 | // } 27 | // if(action.type === 'search_blur'){ 28 | // return { 29 | // focused: false 30 | // } 31 | // } 32 | 33 | default: return state 34 | } 35 | } -------------------------------------------------------------------------------- /react-jianshu/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { GlobalStyle } from './style.js'; 4 | import { IconGlobalStyle } from './static/icon-font/iconfont' 5 | import App from './App'; 6 | 7 | ReactDOM.render( 8 |
    9 | 10 | 11 | 12 |
    13 | , document.getElementById('root')); 14 | 15 | -------------------------------------------------------------------------------- /react-jianshu/src/pages/detail/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import { actionCreators } from './store' 4 | import { withRouter } from 'react-router-dom' 5 | import { 6 | DetailWrapper, 7 | Header, 8 | Content 9 | } from './style' 10 | class Detail extends Component { 11 | componentDidMount() { 12 | this.props.getDetail(this.props.match.params.id) 13 | } 14 | 15 | render() { 16 | console.log(this.props.location.search) 17 | return ( 18 | 19 |
    {this.props.title}
    20 | 21 | 22 |
    23 | ) 24 | } 25 | } 26 | 27 | const mapState = (state) => ({ 28 | title: state.detail.get('title'), 29 | content: state.detail.get('content') 30 | }) 31 | 32 | const mapDispatch = (dispatch) => ({ 33 | getDetail(id) { 34 | dispatch(actionCreators.getDetail(id)) 35 | } 36 | }) 37 | 38 | export default connect(mapState, mapDispatch)(withRouter(Detail)) -------------------------------------------------------------------------------- /react-jianshu/src/pages/detail/loadable.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Loadable from 'react-loadable' 3 | 4 | const LoadableComponent = Loadable({ 5 | loader: () => import('./'), 6 | loading() { 7 | return
    正在加载...
    8 | } 9 | }); 10 | 11 | export default () => -------------------------------------------------------------------------------- /react-jianshu/src/pages/detail/store/actionCreators.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import * as constants from './constants' 3 | 4 | const changeDetail = (title, content) => ({ 5 | type: constants.CHANGE_DETAIL, 6 | title, 7 | content 8 | }) 9 | 10 | export const getDetail = (id) => { 11 | // Vue 写法 12 | // this.$router.push({ path: '/detail', param={}}) 13 | return (dispatch) => { 14 | axios.get('/api/detail.json?id='+id).then(res=> { 15 | console.log(res.data.data) 16 | const result = res.data.data 17 | dispatch(changeDetail(result.title, result.content)) 18 | }) 19 | } 20 | } -------------------------------------------------------------------------------- /react-jianshu/src/pages/detail/store/constants.js: -------------------------------------------------------------------------------- 1 | export const CHANGE_DETAIL = 'detail/CHANGE_DETAIL' -------------------------------------------------------------------------------- /react-jianshu/src/pages/detail/store/index.js: -------------------------------------------------------------------------------- 1 | import reducer from './reducer' 2 | import * as actionCreators from './actionCreators' 3 | import * as constants from './constants' 4 | 5 | export { reducer, actionCreators, constants } -------------------------------------------------------------------------------- /react-jianshu/src/pages/detail/store/reducer.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable' 2 | import * as constants from './constants' 3 | 4 | const defaultState = fromJS({ 5 | title: '', 6 | content: '' 7 | }); 8 | 9 | 10 | export default (state = defaultState, action) => { 11 | switch(action.type){ 12 | case constants.CHANGE_DETAIL: 13 | return state.merge({ 14 | title: action.title, 15 | content: action.content 16 | }) 17 | default: 18 | return state 19 | } 20 | } -------------------------------------------------------------------------------- /react-jianshu/src/pages/detail/style.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const DetailWrapper = styled.div` 4 | overflow: hidden; 5 | width: 720px; 6 | margin: 0 auto; 7 | padding-bottom: 100px; 8 | /* background: red; */ 9 | ` 10 | 11 | export const Header = styled.div` 12 | margin: 40px 0 20px 0; 13 | font-size: 24px; 14 | line-height: 44px; 15 | color: #333; 16 | font-weight: bold; 17 | ` 18 | 19 | export const Content = styled.div` 20 | color: #404040; 21 | img{ 22 | max-height: 1245px; 23 | max-width: 100%; 24 | margin: 0 auto; 25 | display: block; 26 | } 27 | p{ 28 | margin: 25px 0; 29 | color: #2f2f2f; 30 | font-size: 16px; 31 | line-height: 30px; 32 | } 33 | ` -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/components/List.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { ListItem, ListInfo, LoadMore } from '../style' 3 | import { connect } from 'react-redux' 4 | import { actionCreators } from '../store' 5 | import { Link } from 'react-router-dom' 6 | 7 | class List extends Component { 8 | render() { 9 | const { page } = this.props 10 | return ( 11 |
    12 | { 13 | this.props.articleList.map((item, index) => { 14 | return ( 15 | 16 | {/* */} 17 | 18 | {/* */} 19 | 20 | 21 |

    {item.get('title')}

    22 |

    {item.get('desc')}

    23 |
    24 | {/*
    */} 25 |
    26 | 27 | ) 28 | }) 29 | } 30 | this.props.getMoreList(page)}>阅读更多 31 |
    32 | ) 33 | } 34 | } 35 | 36 | const mapState = (state) => ( 37 | { 38 | articleList: state.home.get('articleList'), 39 | page: state.home.get('acticlePage') 40 | } 41 | ) 42 | 43 | // 加载更多需要ajax接口异步请求 44 | const mapDispatch = (dispatch) => ({ 45 | getMoreList(page) { 46 | dispatch(actionCreators.getMoreList(page)) 47 | } 48 | }) 49 | 50 | export default connect(mapState, mapDispatch)(List) -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/components/Recommend.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { RecommendWrapper, RecommendItem } from '../style' 3 | import { connect } from 'react-redux' 4 | 5 | class Recommend extends Component { 6 | render() { 7 | return ( 8 | 9 | { 10 | this.props.list.map((item) => { 11 | return ( 12 | 13 | 14 | 15 | ) 16 | }) 17 | } 18 | 19 | ) 20 | } 21 | } 22 | 23 | const mapState = (state) => ({ 24 | list: state.home.get('recommendList') 25 | }) 26 | 27 | export default connect(mapState, null)(Recommend) -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/components/Topic.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import { TopicWrapper, TopicItem } from '../style' 4 | 5 | class Topic extends Component { 6 | render () { 7 | return ( 8 | 9 | { 10 | this.props.list.map((item) => { 11 | return ( 12 | 13 | 14 | {item.get('title')} 15 | 16 | ) 17 | }) 18 | } 19 | 20 | 21 | ) 22 | } 23 | } 24 | 25 | const mapStateToprops = (state) => ({ 26 | list: state.home.get('topicList') 27 | }) 28 | 29 | export default connect(mapStateToprops, null)(Topic) -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/components/Writer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { WriterWrapper } from '../style' 3 | 4 | 5 | class Writer extends Component { 6 | render () { 7 | return ( 8 | Homework 9 | ) 10 | } 11 | } 12 | 13 | export default Writer -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/store/actionCreators.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import * as constants from './constants' 3 | import { fromJS } from 'immutable' 4 | 5 | const changeHomeData = (result) => ({ 6 | type: constants.CHANGE_HOME_DATA, 7 | topicList: result.topicList, 8 | article: result.articleList, 9 | recommendList: result.recommendList 10 | }) 11 | 12 | const addHomeList = (articleList, nextPage) => ({ 13 | type: constants.ADD_ATRICLE_LIST, 14 | articleList: fromJS(articleList), 15 | nextPage 16 | }) 17 | 18 | export const getHomeInfo = () => { 19 | return (dispatch) => { 20 | axios.get('/api/home.json').then((res) => { 21 | const result = res.data.data 22 | const action = changeHomeData(result) 23 | dispatch(action) 24 | }) 25 | } 26 | } 27 | 28 | export const getMoreList = (page) => { 29 | return (dispatch) => { 30 | axios.get('/api/homeList.json?page=' + page).then((res) => { 31 | const result = res.data.data 32 | const action = addHomeList(result, page + 1) 33 | dispatch(action) 34 | }) 35 | } 36 | } 37 | 38 | export const toggleShow = (show) => ({ 39 | type: constants.TOGGLE_SCROLL_TOP, 40 | show: show 41 | }) -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/store/constants.js: -------------------------------------------------------------------------------- 1 | export const CHANGE_HOME_DATA = 'home/CHANGE_HOME_DATA' 2 | export const ADD_ATRICLE_LIST = 'home/ADD_ATRICLE_LIST' 3 | export const TOGGLE_SCROLL_TOP = 'home/TOGGLE_SCROLL_TOP' -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/store/index.js: -------------------------------------------------------------------------------- 1 | import reducer from './reducer' 2 | import * as actionCreators from './actionCreators' 3 | import * as constants from './constants' 4 | 5 | export { reducer, actionCreators, constants } -------------------------------------------------------------------------------- /react-jianshu/src/pages/home/store/reducer.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable' 2 | import * as constants from './constants' 3 | 4 | const defaultState = fromJS({ 5 | topicList: [], 6 | articleList:[], 7 | recommendList: [], 8 | acticlePage: 1, 9 | showScroll: false 10 | }); 11 | 12 | const changeHomeData = (state, action) => { 13 | return state.merge({ //把多个对象合并成一个对象 14 | topicList: fromJS(action.topicList), 15 | articleList: fromJS(action.article), 16 | recommendList: fromJS(action.recommendList), 17 | }) 18 | } 19 | 20 | const addArticleList = (state, action) => { 21 | return state.merge({ 22 | articleList:state.get('articleList').concat(action.articleList), 23 | acticlePage: action.nextPage 24 | }) 25 | } 26 | 27 | export default (state = defaultState, action) => { 28 | if(action.type === constants.CHANGE_HOME_DATA){ 29 | return changeHomeData(state, action) 30 | } 31 | if(action.type === constants.ADD_ATRICLE_LIST){ 32 | return addArticleList(state, action) 33 | // return state.set('articleList', state.get('articleList').concat(action.articleList)) 34 | } 35 | if(action.type === constants.TOGGLE_SCROLL_TOP){ 36 | return state.set('showScroll' ,action.show) 37 | } 38 | return state 39 | } -------------------------------------------------------------------------------- /react-jianshu/src/pages/login/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | // import { actionCreators } from './store' 3 | import { connect } from 'react-redux' 4 | import { actionCreators } from './store' 5 | import { Redirect } from 'react-router-dom' 6 | import { 7 | LoginWrapper, 8 | LoginBox, 9 | Input, 10 | Button 11 | } from './style' 12 | 13 | class Login extends Component { 14 | render () { 15 | const { login } = this.props 16 | console.log(login) 17 | if (!login) { 18 | return ( 19 | 20 | 21 | {this.account = input}} /> 22 | {this.password = input}}/> 23 | 24 | 25 | 26 | ) 27 | } 28 | else { 29 | return 30 | } 31 | 32 | } 33 | } 34 | 35 | const mapState = (state) => ({ 36 | login: state.login.get('login') 37 | }) 38 | 39 | const mapDispatch = (dispatch) => ({ 40 | login_web(accountItem, passwordItem) { 41 | dispatch(actionCreators.login(accountItem.value, passwordItem.value)) 42 | } 43 | }) 44 | 45 | 46 | export default connect(mapState, mapDispatch)(Login) -------------------------------------------------------------------------------- /react-jianshu/src/pages/login/store/actionCreators.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import {constants} from '../store' 3 | 4 | 5 | const changeLogin= () => ({ 6 | type: constants.CHANGE_LOGIN, 7 | value: true 8 | }) 9 | 10 | export const login = (account, password) => { 11 | return (dispatch) => { 12 | axios.get('/api/login.json?account='+ account + '&password=' + password).then( 13 | (res) => { 14 | const result = res.data.data 15 | if (result) { 16 | dispatch(changeLogin()) 17 | }else{ 18 | alert('登录失败') 19 | } 20 | } 21 | ) 22 | } 23 | } 24 | 25 | export const login_off = () => { 26 | return (dispatch) => { 27 | const action = { 28 | type: constants.LOG_OFF, 29 | value: false 30 | } 31 | dispatch(action) 32 | } 33 | } -------------------------------------------------------------------------------- /react-jianshu/src/pages/login/store/constants.js: -------------------------------------------------------------------------------- 1 | export const CHANGE_LOGIN = 'login/CHANGE_LOGIN' 2 | export const LOG_OFF = 'login/LOG_OFF' -------------------------------------------------------------------------------- /react-jianshu/src/pages/login/store/index.js: -------------------------------------------------------------------------------- 1 | import reducer from './reducer' 2 | import * as actionCreators from './actionCreators' 3 | import * as constants from './constants' 4 | 5 | export { reducer, actionCreators, constants } -------------------------------------------------------------------------------- /react-jianshu/src/pages/login/store/reducer.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable' 2 | import * as constants from './constants' 3 | // immutable.js 4 | // facebook 5 | // immutable对象 6 | 7 | const defaultState = fromJS({ 8 | login: false 9 | }) 10 | 11 | export default (state = defaultState, action) => { 12 | switch (action.type) { 13 | case constants.CHANGE_LOGIN: 14 | return state.set('login', action.value) 15 | case constants.LOG_OFF: 16 | return state.set('login', action.value) 17 | default: 18 | return state 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /react-jianshu/src/pages/login/style.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const LoginWrapper = styled.div` 4 | position: absolute; 5 | left: 0; 6 | right: 0; 7 | bottom: 0; 8 | top: 56px; 9 | background: #eee; 10 | 11 | ` 12 | 13 | export const LoginBox = styled.div` 14 | padding-top: 80px; 15 | width: 400px; 16 | height: 320px; 17 | margin: 50px auto; 18 | background: #fff; 19 | box-shadow: 0 0 8px rgba(0, 0, 0, .1); 20 | box-sizing: border-box; 21 | ` 22 | 23 | export const Input = styled.input` 24 | display: block; 25 | width: 200px; 26 | height: 30px; 27 | line-height: 30px; 28 | color: #777; 29 | margin: 10px auto; 30 | padding: 0 10px; 31 | /* border: 1px solid #000; */ 32 | ` 33 | 34 | export const Button = styled.div` 35 | display: block; 36 | width: 200px; 37 | height: 30px; 38 | color: #fff; 39 | line-height: 30px; 40 | background: #3194d0; 41 | border-radius: 10px; 42 | margin: 30px auto; 43 | text-align: center; 44 | ` -------------------------------------------------------------------------------- /react-jianshu/src/pages/write/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | // import { actionCreators } from './store' 3 | import { connect } from 'react-redux' 4 | import { Redirect } from 'react-router-dom' 5 | 6 | 7 | class Write extends Component { 8 | render () { 9 | const { loginState } = this.props 10 | if (loginState) { 11 | return ( 12 |
    写文章页面
    13 | ) 14 | } 15 | else { 16 | return 17 | } 18 | 19 | } 20 | } 21 | 22 | const mapState = (state) => ({ 23 | loginState: state.login.get('login') 24 | }) 25 | 26 | 27 | export default connect(mapState, null)(Write) -------------------------------------------------------------------------------- /react-jianshu/src/static/icon-font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/src/static/icon-font/iconfont.eot -------------------------------------------------------------------------------- /react-jianshu/src/static/icon-font/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1688023", 3 | "name": "jianshu", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon", 6 | "description": "这是简书icon仓库", 7 | "glyphs": [ 8 | { 9 | "icon_id": "2356808", 10 | "name": "毛笔", 11 | "font_class": "maobi", 12 | "unicode": "e62e", 13 | "unicode_decimal": 58926 14 | }, 15 | { 16 | "icon_id": "8158665", 17 | "name": "Aa", 18 | "font_class": "Aa", 19 | "unicode": "e698", 20 | "unicode_decimal": 59032 21 | }, 22 | { 23 | "icon_id": "8546046", 24 | "name": "放大镜", 25 | "font_class": "fangdajing", 26 | "unicode": "e63f", 27 | "unicode_decimal": 58943 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /react-jianshu/src/static/icon-font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/src/static/icon-font/iconfont.ttf -------------------------------------------------------------------------------- /react-jianshu/src/static/icon-font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/src/static/icon-font/iconfont.woff -------------------------------------------------------------------------------- /react-jianshu/src/static/icon-font/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/src/static/icon-font/iconfont.woff2 -------------------------------------------------------------------------------- /react-jianshu/src/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-jianshu/src/static/logo.png -------------------------------------------------------------------------------- /react-jianshu/src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore, compose, applyMiddleware } from 'redux' 2 | import reducer from './reducer' 3 | import thunk from 'redux-thunk' 4 | 5 | const componentEnhanders = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; 6 | 7 | const enhancer = componentEnhanders( 8 | applyMiddleware(thunk) 9 | // applyMiddleware(sagaMiddleware) 10 | ) 11 | const store = createStore(reducer, enhancer) 12 | 13 | export default store; -------------------------------------------------------------------------------- /react-jianshu/src/store/reducer.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | import { reducer as headerReducer } from '../common/header/store' 3 | import { reducer as homeReducer } from '../pages/home/store' 4 | import { reducer as detailReducer } from '../pages/detail/store' 5 | import { reducer as loginReducer } from '../pages/login/store' 6 | // 合并小的reducer 7 | const reducer = combineReducers({ 8 | header: headerReducer, 9 | home: homeReducer, 10 | detail: detailReducer, 11 | login: loginReducer 12 | }) 13 | 14 | export default reducer -------------------------------------------------------------------------------- /react-jianshu/src/style.js: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components' 2 | 3 | export const GlobalStyle = createGlobalStyle` 4 | body { 5 | margin: 0; 6 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 7 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 8 | sans-serif; 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | 13 | code { 14 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 15 | monospace; 16 | } 17 | 18 | html, body, div, span, applet, object, iframe, 19 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 20 | a, abbr, acronym, address, big, cite, code, 21 | del, dfn, em, img, ins, kbd, q, s, samp, 22 | small, strike, strong, sub, sup, tt, var, 23 | b, u, i, center, 24 | dl, dt, dd, ol, ul, li, 25 | fieldset, form, label, legend, 26 | table, caption, tbody, tfoot, thead, tr, th, td, 27 | article, aside, canvas, details, embed, 28 | figure, figcaption, footer, header, hgroup, 29 | menu, nav, output, ruby, section, summary, 30 | time, mark, audio, video { 31 | margin: 0; 32 | padding: 0; 33 | border: 0; 34 | font-size: 100%; 35 | font: inherit; 36 | vertical-align: baseline; 37 | color: #000; 38 | } 39 | /* HTML5 display-role reset for older browsers */ 40 | article, aside, details, figcaption, figure, 41 | footer, header, hgroup, menu, nav, section { 42 | display: block; 43 | } 44 | body { 45 | line-height: 1; 46 | } 47 | ol, ul { 48 | list-style: none; 49 | } 50 | blockquote, q { 51 | quotes: none; 52 | } 53 | blockquote:before, blockquote:after, 54 | q:before, q:after { 55 | content: ''; 56 | content: none; 57 | } 58 | table { 59 | border-collapse: collapse; 60 | border-spacing: 0; 61 | } 62 | ` 63 | -------------------------------------------------------------------------------- /react-jianshu/加载更多.md: -------------------------------------------------------------------------------- 1 | ``` 2 | { 3 | this.props.showScroll ? 回到顶部 : null 4 | } 5 | componentDidMount () { 6 | this.props.changeHomeData() 7 | this.bindEvents() 8 | } 9 | 10 | bindEvents(){ 11 | window.addEventListener('scroll', this.props.changeScrollTopShow) 12 | } 13 | 14 | handleScrollTop () { 15 | window.scrollTo(0,0) 16 | } 17 | ``` 18 | 19 | >因为是绑定到window上的,因此在组件卸载(跳转到其它页面的时候需要移除该事件) 20 | componentWillMount() { 21 | window.removeEventListener('scroll', this.props.changeScrollTopShow) 22 | } 23 | -------------------------------------------------------------------------------- /react-react-redux/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-react-redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-react-redux", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.13.0", 10 | "react-dom": "^16.13.0", 11 | "react-redux": "^7.2.0", 12 | "react-scripts": "3.4.0" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /react-react-redux/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-react-redux/public/favicon.ico -------------------------------------------------------------------------------- /react-react-redux/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-react-redux/public/logo192.png -------------------------------------------------------------------------------- /react-react-redux/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-react-redux/public/logo512.png -------------------------------------------------------------------------------- /react-react-redux/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-react-redux/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-react-redux/src/TodoList.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | // import store from './store' 3 | import { connect } from 'react-redux' 4 | 5 | class TodoList extends Component { 6 | // constructor(props) { 7 | // super(props) 8 | // this.state = store.getState() 9 | // } 10 | 11 | // handleInputChange(e) { 12 | // //用这个值替换store里inputValue的值 13 | // console.log(e.target.value) 14 | // const action = 15 | // this.props.dispatch(action) 16 | // } 17 | 18 | render () { 19 | return ( 20 |
    21 |
    22 | 23 | 24 |
    25 |
      26 |
    • {this.props.list}
    • 27 |
    28 |
    29 | ) 30 | } 31 | } 32 | 33 | // 遍历state里面的所有数据给到props 34 | const mapStateToProps = (state) => { 35 | return { 36 | inputValue: state.inputValue, 37 | list: state.list 38 | } 39 | } 40 | 41 | const mapDispatchToProps = (dispatch) => { // 把store.dispatch 挂载到props上 42 | return { 43 | changeInputValue (e) { 44 | const action = { 45 | type : 'change_input_value', 46 | value: e.target.value 47 | } 48 | console.log(action) 49 | // const action = getChangeInputAction(e.target.value) 50 | dispatch(action) 51 | } 52 | } 53 | } 54 | 55 | // connect 是连接 56 | // TodoList 和 store 做连接 57 | // mapStateToProps 的参数就是 store里面的数据 该方法会帮助我们把store映射到props 58 | 59 | export default connect(mapStateToProps, mapDispatchToProps)(TodoList) -------------------------------------------------------------------------------- /react-react-redux/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import TodoList from './TodoList' 4 | import { Provider } from 'react-redux' 5 | import store from './store' 6 | 7 | // Provider 连接器连接了store, 那么Provider里面的所有的组件都具备了使用store里面的内容的权力 8 | const App = ( 9 | 10 | 11 | 12 | ) 13 | 14 | ReactDOM.render(App, document.getElementById('root')); 15 | 16 | -------------------------------------------------------------------------------- /react-react-redux/src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'redux' 2 | import reducer from './reducer' 3 | 4 | const store = createStore(reducer) 5 | 6 | export default store -------------------------------------------------------------------------------- /react-react-redux/src/store/reducer.js: -------------------------------------------------------------------------------- 1 | const defaultState = { 2 | inputValue: '123', 3 | list: [1], 4 | data:[] 5 | } 6 | 7 | export default (state = defaultState, action) => { 8 | if(action.type === 'change_input_value'){ 9 | const newState = JSON.parse(JSON.stringify(state)) 10 | newState.list.push(action.value) 11 | console.log(newState.list) 12 | return newState // reducer 有一个限制, 可以接收state, 但是绝对不能修改state 13 | } 14 | return state 15 | } -------------------------------------------------------------------------------- /react-redux/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-redux/README.md: -------------------------------------------------------------------------------- 1 | # reducer 有一个限制, 可以接收state, 但是绝对不能修改state 2 | 3 | # redux 4 | 1. 用react 实现todolist 5 | 2. 加入reudx 6 | 3. actionTypes 整合 7 | 4. 使用actionCreator 统一创建 action 8 | 9 | # 总结 redux的设计使用原则 10 | 1. store 是唯一的 11 | 2. 只有store能改变自己的内容 12 | 3. reducer 是一个纯函数 13 | 14 | # redux中的核心API 15 | 1. createStore 创建store 16 | 2. store.dispatch 派发action 17 | 3. store.getState 获取store里面所有的数据 18 | 4. store.subscribe 订阅store数据的改变 19 | 20 | # UI组件与容器组件 21 | UI组件: 渲染页面 -> 一般定义成无状态组件 function 22 | 容器组件: 逻辑操作 23 | 24 | # 无状态组件 25 | 26 | # Redux中发送异步请求获取数据 27 | 28 | # redux-thunk ajax数据请求 29 | 30 | # 什么是 Redux 中间件 31 | 32 | # redux-saga 中间件 ajax数据请求 33 | 34 | # react-redux 35 | 36 | -------------------------------------------------------------------------------- /react-redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-redux", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "antd": "^4.0.2", 10 | "axios": "^0.19.2", 11 | "react": "^16.13.0", 12 | "react-dom": "^16.13.0", 13 | "react-scripts": "3.4.0", 14 | "redux": "^4.0.5", 15 | "redux-saga": "^1.1.3", 16 | "redux-thunk": "^2.3.0", 17 | "save": "^2.4.0" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": "react-app" 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /react-redux/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-redux/public/favicon.ico -------------------------------------------------------------------------------- /react-redux/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-redux/public/logo192.png -------------------------------------------------------------------------------- /react-redux/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-redux/public/logo512.png -------------------------------------------------------------------------------- /react-redux/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-redux/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-redux/redux 原理图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-redux/redux 原理图.jpg -------------------------------------------------------------------------------- /react-redux/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-redux/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-redux/src/TodoListUI.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Input, Button, List} from 'antd' 3 | 4 | // class TodoListUI extends Component { 5 | // render() { 6 | // return ( 7 | //
    8 | //
    9 | // 11 | // 12 | //
    13 | // 18 | // ( 19 | // this.props.handleItemDelete(index) 20 | // )}> 21 | // {item} 22 | // } 23 | // /> 24 | //
    25 | // ) 26 | // } 27 | // } 28 | 29 | const TodoListUI = (props) => { 30 | return ( 31 |
    32 |
    33 | 35 | 36 |
    37 | 42 | ( 43 | props.handleItemDelete(index) 44 | )}> 45 | {item} 46 | } 47 | /> 48 |
    49 | ) 50 | } 51 | 52 | export default TodoListUI -------------------------------------------------------------------------------- /react-redux/src/assets/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": ["hello", "Tom", "Jerry"] 3 | } -------------------------------------------------------------------------------- /react-redux/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react-redux/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import TodoList from './TodoList'; 4 | import * as serviceWorker from './serviceWorker'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | 8 | // If you want your app to work offline and load faster, you can change 9 | // unregister() to register() below. Note this comes with some pitfalls. 10 | // Learn more about service workers: https://bit.ly/CRA-PWA 11 | serviceWorker.unregister(); 12 | -------------------------------------------------------------------------------- /react-redux/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /react-redux/src/store/actionCreators.js: -------------------------------------------------------------------------------- 1 | import { CHANGE_INPUT_VALUE, ADD_TODO_LIST, DELETE_TODO_ITEM, INIT_LIST_ACTION, GET_INIT_LIST } from './actionTypes' 2 | import axios from 'axios' 3 | 4 | export const getInputChangeAction = (value) => ({ 5 | type: CHANGE_INPUT_VALUE, 6 | value 7 | }) 8 | 9 | export const getAddAction = () => ({ 10 | type: ADD_TODO_LIST 11 | }) 12 | 13 | export const getDeleteItemAction = (index) => ({ 14 | type: DELETE_TODO_ITEM, 15 | index 16 | }) 17 | 18 | export const initListAction = (data) => ({ 19 | type: INIT_LIST_ACTION, 20 | data 21 | }) 22 | 23 | // redux thunk 24 | // export const getTodoList = () => { 25 | // return (dispatch) => { 26 | // axios.get('http://musicapi.leanapp.cn/comment/music?id=186016&limit=1').then( 27 | // (res) => { 28 | // const data = res.data 29 | // const action = initListAction(Object.keys(data.hotComments[0])) 30 | // // store.dispatch(action) 31 | // console.log(action) 32 | // dispatch(action) 33 | // } 34 | // ) 35 | // } 36 | // } 37 | 38 | export const getInitList = () => ({ 39 | type: GET_INIT_LIST 40 | }) -------------------------------------------------------------------------------- /react-redux/src/store/actionTypes.js: -------------------------------------------------------------------------------- 1 | export const CHANGE_INPUT_VALUE = 'change_input_value' 2 | export const ADD_TODO_LIST = 'add_todo_list' 3 | export const DELETE_TODO_ITEM = 'delete_todo_item' 4 | export const INIT_LIST_ACTION = 'init_list_action' 5 | export const GET_INIT_LIST = 'get_init_list' 6 | -------------------------------------------------------------------------------- /react-redux/src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, compose } from 'redux' 2 | import reducer from './reducer' 3 | import thunk from 'redux-thunk' 4 | import createSagaMiddleware from 'redux-saga' 5 | import todoSagas from './sagas' 6 | 7 | const sagaMiddleware = createSagaMiddleware() 8 | 9 | const componentEnhanders = 10 | window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? 11 | window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ({ 12 | }) : compose; 13 | 14 | const enhancer = componentEnhanders( 15 | // applyMiddleware(thunk) 16 | applyMiddleware(sagaMiddleware) 17 | ) 18 | 19 | const store = createStore( 20 | reducer, 21 | enhancer 22 | ) 23 | 24 | sagaMiddleware.run(todoSagas) 25 | 26 | //store默认状态 27 | // store = { 28 | // inputValue: '123', 29 | // list: [] 30 | // } 31 | // 经过逻辑操作 32 | // store将自己的值变为newState -> store能改变自己的内容 33 | 34 | export default store; -------------------------------------------------------------------------------- /react-redux/src/store/reducer.js: -------------------------------------------------------------------------------- 1 | import {CHANGE_INPUT_VALUE, ADD_TODO_LIST, DELETE_TODO_ITEM, INIT_LIST_ACTION } from './actionTypes.js' 2 | 3 | const defaultState = { 4 | inputValue: '123', 5 | list: [], 6 | data:[] 7 | } 8 | 9 | // state 指的是 stroe里面上一次存储的数据 10 | // 纯函数指的是,给定固定的输入,就一定会有固定的输出,而不会有任何副作用 11 | export default (state = defaultState, action) => { 12 | if(action.type === CHANGE_INPUT_VALUE){ 13 | const newState = JSON.parse(JSON.stringify(state)) 14 | newState.inputValue = action.value 15 | return newState // reducer 有一个限制, 可以接收state, 但是绝对不能修改state 16 | } 17 | if(action.type === ADD_TODO_LIST){ 18 | const newState = JSON.parse(JSON.stringify(state)) 19 | // console.log(newState.inputValue) 20 | if(newState.inputValue===''){ 21 | return newState 22 | } 23 | newState.list.push(newState.inputValue) 24 | // console.log(newState.list) 25 | newState.inputValue = '' 26 | return newState 27 | } 28 | if(action.type === DELETE_TODO_ITEM ){ 29 | const newState = JSON.parse(JSON.stringify(state)) 30 | newState.list.splice(action.index,1) 31 | return newState 32 | } 33 | if(action.type === INIT_LIST_ACTION){ 34 | const newState = JSON.parse(JSON.stringify(state)) 35 | newState.list = action.data 36 | return newState 37 | } 38 | // console.log(state, action) 39 | return state 40 | } -------------------------------------------------------------------------------- /react-redux/src/store/sagas.js: -------------------------------------------------------------------------------- 1 | import { takeEvery, put } from 'redux-saga/effects' 2 | import { GET_INIT_LIST } from './actionTypes' 3 | import { initListAction } from './actionCreators' 4 | import axios from 'axios' 5 | 6 | function* getInitList() { 7 | try{ 8 | const res = yield axios.get('http://musicapi.leanapp.cn/comment/music?id=186016&limit=1') 9 | const action = initListAction(Object.keys(res.data.hotComments[0])) 10 | yield put(action) 11 | } catch(e){ 12 | console.log('网络请求失败') 13 | } 14 | 15 | // axios.get('http://musicapi.leanapp.cn/comment/music?id=186016&limit=1').then( 16 | // (res) => { 17 | // const data = res.data 18 | // const action = initListAction(Object.keys(data.hotComments[0])) 19 | // console.log(action) 20 | 21 | // } 22 | // ) 23 | } 24 | 25 | function* mySaga() { // sagas 必须要是 generator函数 26 | yield takeEvery(GET_INIT_LIST, getInitList); 27 | } 28 | 29 | export default mySaga; -------------------------------------------------------------------------------- /react-router-antd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-router-antd", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "antd": "^4.0.0", 10 | "react": "^16.13.0", 11 | "react-dom": "^16.13.0", 12 | "react-router-dom": "^5.1.2", 13 | "react-scripts": "3.4.0" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /react-router-antd/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-router-antd/public/favicon.ico -------------------------------------------------------------------------------- /react-router-antd/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-router-antd/public/logo192.png -------------------------------------------------------------------------------- /react-router-antd/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-router-antd/public/logo512.png -------------------------------------------------------------------------------- /react-router-antd/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-router-antd/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-router-antd/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-router-antd/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { BrowserRouter as Router, Route, Link } from 'react-router-dom' 3 | import 'antd/dist/antd.css'; 4 | import Layout from './pages/Layout' 5 | 6 | function App() { 7 | return ( 8 | 9 | 10 | 11 | ) 12 | } 13 | 14 | export default App -------------------------------------------------------------------------------- /react-router-antd/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-router-antd/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react-router-antd/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /react-router-antd/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /react-router/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-router", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.13.0", 10 | "react-dom": "^16.13.0", 11 | "react-router-dom": "^5.1.2", 12 | "react-scripts": "3.4.0" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /react-router/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-router/public/favicon.ico -------------------------------------------------------------------------------- /react-router/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-router/public/logo192.png -------------------------------------------------------------------------------- /react-router/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/react-router/public/logo512.png -------------------------------------------------------------------------------- /react-router/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /react-router/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /react-router/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-router/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /react-router/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react-router/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /react-router/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## React学习 -------------------------------------------------------------------------------- /weather/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /weather/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /weather/config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFilename = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFilename}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /weather/config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /weather/public/city/hotcity.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true, 3 | "aaa": 2, 4 | "hotList":["北京", "广州", "深圳", "上海", "南京", "杭州", "武汉"] 5 | } -------------------------------------------------------------------------------- /weather/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/public/favicon.ico -------------------------------------------------------------------------------- /weather/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/public/logo192.png -------------------------------------------------------------------------------- /weather/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/public/logo512.png -------------------------------------------------------------------------------- /weather/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /weather/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /weather/scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | 19 | const jest = require('jest'); 20 | const execSync = require('child_process').execSync; 21 | let argv = process.argv.slice(2); 22 | 23 | function isInGitRepository() { 24 | try { 25 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 26 | return true; 27 | } catch (e) { 28 | return false; 29 | } 30 | } 31 | 32 | function isInMercurialRepository() { 33 | try { 34 | execSync('hg --cwd . root', { stdio: 'ignore' }); 35 | return true; 36 | } catch (e) { 37 | return false; 38 | } 39 | } 40 | 41 | // Watch unless on CI or explicitly running all tests 42 | if ( 43 | !process.env.CI && 44 | argv.indexOf('--watchAll') === -1 && 45 | argv.indexOf('--watchAll=false') === -1 46 | ) { 47 | // https://github.com/facebook/create-react-app/issues/5210 48 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 49 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 50 | } 51 | 52 | 53 | jest.run(argv); 54 | -------------------------------------------------------------------------------- /weather/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /weather/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router , Route} from 'react-router-dom' 3 | import './App.css'; 4 | import 'antd/dist/antd.css' 5 | import MainPage from './pages/main' 6 | import SearchCity from './pages/search' 7 | import { Provider } from 'react-redux' 8 | import store from './store' 9 | import Test from './pages/test'; 10 | 11 | function App() { 12 | return ( 13 | 14 | 15 |
    16 | 17 | 18 |
    19 |
    20 |
    21 | ); 22 | } 23 | 24 | export default App; 25 | -------------------------------------------------------------------------------- /weather/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /weather/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /weather/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /weather/src/pages/main/component/cloudy.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Cloudy, Sunny } from './style' 3 | 4 | class WeatherCircle extends React.Component { 5 | render() { 6 | return ( 7 | 8 | 9 | 10 | // 11 | // 12 | // 13 | 14 | ) 15 | } 16 | } 17 | 18 | export default WeatherCircle -------------------------------------------------------------------------------- /weather/src/pages/main/component/style.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const Cloudy = styled.div` 4 | position: absolute; 5 | right: 30px; 6 | top: 30px; 7 | width: 80px; 8 | height: 80px; 9 | border-radius: 100%; 10 | background: linear-gradient(to top right,#000000 0,#eee 90%); 11 | box-shadow: 0 0 0 0.1px #280000, 0 0 10px -1px #C0C0C0; 12 | .cloud { 13 | position: absolute; 14 | top: 25%; 15 | left: 40%; 16 | width: 20px; 17 | height: 6px; 18 | border-radius: 4px; 19 | background-color: #eee; 20 | box-shadow: 0 0 4px 2px #e6e8db,0 0 20px -2px #c9e8de; 21 | animation: move 4000ms infinite ease-in-out; 22 | } 23 | @keyframes move { 24 | 50% { 25 | transform: translateX(-10px); 26 | } 27 | } 28 | .cloud::before { 29 | left: 3px; 30 | height: 10px; 31 | width: 10px; 32 | } 33 | .cloud::after { 34 | left: 9px; 35 | height: 7px; 36 | width: 7px; 37 | } 38 | .cloud::before, .cloud::after { 39 | content: ''; 40 | position: inherit; 41 | border-radius: 100%; 42 | background-color: inherit; 43 | box-shadow: inherit; 44 | bottom: 40%; 45 | } 46 | ` 47 | 48 | export const Sunny = styled.div` 49 | position: absolute; 50 | right: 30px; 51 | top: 30px; 52 | width: 80px; 53 | height: 80px; 54 | border-radius: 100%; 55 | background: linear-gradient(to top right, #fc5830 0%, #f98c24 65%); 56 | box-shadow: 0 0 0 1px #e6e8db,0 0 10px -1px #c9e8de; 57 | .sun{ 58 | position: absolute; 59 | top: 20%; 60 | left: 80%; 61 | transform: translate(-50%, -50%); 62 | width: 40%; 63 | height: 40%; 64 | border-radius: 100%; 65 | background: #ffeb3b; 66 | box-shadow: 0 0 0 0.02em #e6e8db, 0 0 0.3em -0.03em #fd6f21; 67 | } 68 | ` 69 | 70 | -------------------------------------------------------------------------------- /weather/src/pages/main/loadable.js: -------------------------------------------------------------------------------- 1 | import Loadable from 'react-loadable'; 2 | 3 | const LoadableComponent = Loadable({ 4 | loader: () => import('./index'), 5 | loading() { 6 | return
    正在加载...
    7 | } 8 | }); 9 | 10 | export default () => -------------------------------------------------------------------------------- /weather/src/pages/search/loadable.js: -------------------------------------------------------------------------------- 1 | import Loadable from 'react-loadable'; 2 | 3 | const LoadableComponent = Loadable({ 4 | loader: () => import('./index'), 5 | loading() { 6 | return
    正在加载...
    7 | } 8 | }); 9 | 10 | export default () => -------------------------------------------------------------------------------- /weather/src/pages/search/style.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const SearchWrapper = styled.div` 4 | margin: 0; 5 | padding: 10px 10px 0 10px; 6 | button{ 7 | right: 10px; 8 | position: absolute; 9 | } 10 | a{ 11 | color: #000; 12 | } 13 | ` 14 | 15 | export const Recommend = styled.div` 16 | padding-top: 25px; 17 | box-sizing: border-box; 18 | p{ 19 | font-weight: bold; 20 | padding-left: 3px; 21 | } 22 | ` 23 | 24 | export const TagWrapper = styled.div` 25 | width: 112px; 26 | height: 25px; 27 | text-align: center; 28 | line-height: 25px; 29 | background: #eee; 30 | font-size: 12px; 31 | margin: 4px 6px 2px 0; 32 | ` 33 | export const Tag = styled.div` 34 | display: flex; 35 | flex-wrap: wrap; 36 | justify-content: space-between; 37 | box-sizing: border-box; 38 | ` 39 | export const His = styled.div` 40 | display: flex; 41 | flex-wrap: wrap; 42 | /* justify-content: space-between; */ 43 | justify-content: flex-start; 44 | box-sizing: border-box; 45 | ` 46 | -------------------------------------------------------------------------------- /weather/src/pages/test/index.js: -------------------------------------------------------------------------------- 1 | import { Select } from 'antd'; 2 | import React from 'react' 3 | import axios from 'axios' 4 | const { Option } = Select; 5 | let timeout; 6 | let currentValue; 7 | 8 | function fetch(value, callback) { 9 | if (timeout) { 10 | clearTimeout(timeout); 11 | timeout = null; 12 | } 13 | currentValue = value; 14 | 15 | function fake() { 16 | axios.get('/city/citys.json').then((res) => { 17 | var tem = [] 18 | tem = res.data.citys.filter((item) => item.citysName.includes(value)) 19 | // this.setState({ 20 | // showsearch: this.tem[0].citys.slice(0,15) 21 | // }) 22 | console.log(tem.slice(0,10)) 23 | callback(tem.slice(0,10)) 24 | }) 25 | } 26 | 27 | timeout = setTimeout(fake, 300); 28 | } 29 | 30 | class SearchInput extends React.Component { 31 | state = { 32 | data: [], 33 | value: undefined, 34 | }; 35 | 36 | handleSearch = value => { 37 | if (value) { 38 | fetch(value, data => this.setState({ data })); 39 | } else { 40 | this.setState({ data: [] }); 41 | } 42 | }; 43 | 44 | handleChange = value => { 45 | this.setState({ value }); 46 | }; 47 | 48 | render() { 49 | console.log(this.state.data) 50 | const options = this.state.data.map(d => ); 51 | return ( 52 | 66 | ); 67 | } 68 | } 69 | 70 | export default SearchInput -------------------------------------------------------------------------------- /weather/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /weather/src/static/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/iconfont/iconfont.eot -------------------------------------------------------------------------------- /weather/src/static/iconfont/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1714637", 3 | "name": "weather", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon-", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "10836545", 10 | "name": "叶子", 11 | "font_class": "yezi", 12 | "unicode": "e663", 13 | "unicode_decimal": 58979 14 | }, 15 | { 16 | "icon_id": "12924200", 17 | "name": "口罩", 18 | "font_class": "kouzhao", 19 | "unicode": "e640", 20 | "unicode_decimal": 58944 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /weather/src/static/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /weather/src/static/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/iconfont/iconfont.woff -------------------------------------------------------------------------------- /weather/src/static/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /weather/src/static/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/1.jpg -------------------------------------------------------------------------------- /weather/src/static/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/2.jpg -------------------------------------------------------------------------------- /weather/src/static/img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/3.jpg -------------------------------------------------------------------------------- /weather/src/static/img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/4.jpg -------------------------------------------------------------------------------- /weather/src/static/img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/5.jpg -------------------------------------------------------------------------------- /weather/src/static/img/中雨.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/中雨.png -------------------------------------------------------------------------------- /weather/src/static/img/多云.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/多云.png -------------------------------------------------------------------------------- /weather/src/static/img/大雨.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/大雨.png -------------------------------------------------------------------------------- /weather/src/static/img/小雨.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/小雨.png -------------------------------------------------------------------------------- /weather/src/static/img/晴.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/晴.png -------------------------------------------------------------------------------- /weather/src/static/img/阴.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/阴.png -------------------------------------------------------------------------------- /weather/src/static/img/阵雨.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/阵雨.png -------------------------------------------------------------------------------- /weather/src/static/img/雷阵雨.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmCas/React-study/19cc2c81b77f0850c1e029050b260447c849624d/weather/src/static/img/雷阵雨.png -------------------------------------------------------------------------------- /weather/src/store/actionCreators.js: -------------------------------------------------------------------------------- 1 | // import axios from 'axios' 2 | import * as actionTypes from './actionTypes' 3 | 4 | const cityApi = (city) => ({ 5 | type: actionTypes.CURRENT_CITY, 6 | city 7 | }) 8 | 9 | const weatherApi = (data) => ({ 10 | type: actionTypes.CURRENT_WEATHER, 11 | weatherData: data 12 | }) 13 | 14 | const forecastApi = (data) => ({ 15 | type: actionTypes.FORECAST_WEATHER, 16 | forecast: data 17 | }) 18 | 19 | export const getCity = (city) => { 20 | return (dispatch) => { 21 | const action = cityApi(city) 22 | dispatch(action) 23 | } 24 | } 25 | 26 | export const getWeather = (data) => { 27 | return (dispatch) => { 28 | const action = weatherApi(data) 29 | dispatch(action) 30 | } 31 | } 32 | 33 | export const getForecast = (data) => { 34 | return (dispatch) => { 35 | const action = forecastApi(data) 36 | dispatch(action) 37 | } 38 | } 39 | 40 | export const getInit = () => { 41 | return (dispatch) => { 42 | const action = { 43 | type : actionTypes.FIRST_INIT, 44 | init: false 45 | } 46 | dispatch(action) 47 | } 48 | } 49 | 50 | export const changeCity = (city) => { 51 | return dispatch => { 52 | const action = { 53 | type : actionTypes.CHANGE_CITY, 54 | city: city 55 | } 56 | dispatch(action) 57 | } 58 | } -------------------------------------------------------------------------------- /weather/src/store/actionTypes.js: -------------------------------------------------------------------------------- 1 | export const CURRENT_CITY = 'home/CURRENT_CITY' 2 | export const CURRENT_WEATHER = 'home/CURRENT_WEATHER' 3 | export const FORECAST_WEATHER = 'home/ORECAST_WEATHER' 4 | 5 | export const FIRST_INIT = 'home/FIRST_INIT' 6 | export const CHANGE_CITY = 'search/FIRST_INIT' -------------------------------------------------------------------------------- /weather/src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore, compose, applyMiddleware } from 'redux' 2 | import reducer from './reducer' 3 | import thunk from 'redux-thunk' 4 | 5 | const componentEnhanders = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; 6 | 7 | const enhancer = componentEnhanders( 8 | applyMiddleware(thunk) 9 | ) 10 | const store = createStore(reducer, enhancer) 11 | 12 | export default store -------------------------------------------------------------------------------- /weather/src/store/reducer.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable' 2 | import * as actionTypes from './actionTypes' 3 | 4 | const defaultState = fromJS({ 5 | city: '', 6 | cityHistory: [], 7 | weatherData: {}, 8 | forecast: [], 9 | init: true 10 | }) 11 | 12 | export default (state = defaultState, action) => { 13 | if (action.type === actionTypes.CURRENT_CITY) { 14 | return state.set('city', action.city) 15 | } 16 | if (action.type === actionTypes.CURRENT_WEATHER) { 17 | return state.set('weatherData', action.weatherData) 18 | } 19 | if (action.type === actionTypes.FORECAST_WEATHER) { 20 | console.log(action.forecast) 21 | return state.set('forecast', action.forecast) 22 | } 23 | if (action.type === actionTypes.FIRST_INIT) { 24 | return state.set('init', false) 25 | } 26 | if (action.type === actionTypes.CHANGE_CITY) { 27 | return state.merge({ 28 | city: action.city, 29 | cityHistory:[...new Set(state.get('cityHistory').concat(action.city))] 30 | } 31 | ) 32 | } 33 | return state 34 | } --------------------------------------------------------------------------------