最近两个星期在搬家, 我记得在上小学还是什么时候, 家里搬过一次家, 那一次实际上只不过是同一个小区的房子搬到了另外一个房子.
至此以后, 在我的生活里除了出来上大学和换租的房子之外, 并没有真正的搬家, 因为那个时候, 还没有自己的家.
每天晚上蚂蚁搬家一样一点一滴的把东西搬到新租的房子里, 然后看着老房子不断变空, 有很多角落旮旯, 从住进来之后从未看过.
现在到了离开的时候, 反而却显露在外边, 似乎就是在说,再多看我两眼吧,以后机会可就不多了.
以前读的儿童心理学相关的书里会写, 小孩对于旧房子可能会有着特别的留恋, 还可能会在搬家之后提出来想过来看看.
由于后边女儿的英语课也快上完了, 昨天晚上很可能就是她在家里睡的最后一晚, 今天就要把她送去外婆家了.
于是我给他提个建议, 可以拍一些照片留念, 晚上到了睡觉之前, 小家伙就缠着妈妈来拍照片.
她确认了现在家里的沙发不会搬到新家, 就要老妈拍在沙发上跳跃和站在沙发背上的照片, 然后就是在床上的照片.
拍好了之后, 爱讲话的女儿自然还有连篇累牍的问题: 妈妈房子还能回来吗? 妈妈房子还能进来看吗? 妈妈我们有钥匙不就可以回来了吗?
哈哈, 她晚上例行睡前要和我聊天的时候说, 为什么要搬家的感觉有点伤心呢...
在交房之前, 我们也已经商量好, 一家三口在老房子的各个地方合影留念.
现在的房子就是我和老婆的婚房, 2012年购入, 2013年5月住进来, 到现在7年多3个月.如果算上在妈妈肚里的时间, 女儿也有整整七年的时间呆在这里了,无论是婚姻还是孩子,这个房子都见证了目前为止完整的历史,想想要搬走还真的有点舍不得.况且房子多层带电梯, 靠西双阳台, 虽然不算大, 94平米的两房, 但算是小区里最好的两房户型, 住起来也非常舒服.
最近女儿喜欢看乘风破浪的姐姐, 然后天天唱其中的歌. 有两句话我印象深刻: 人生太多意外 来不及停留感慨... 不管怎么样, 新的起点, 再次出发吧!
之前简单回看了一下ES6和Node, 基本的操作知道了, 现在来开始看React. 这次的视频是: Udemy - Complete React Developer in 2020 (w Redux, Hooks, GraphQL), 可以在这里下载.
React
如果要编写React App, 首先需要有一个编辑器, 使用WebStorm即可. 然后需要一个创建ReactApp的东西, 在React官网这里可以找到 Create a New React App, 需要安装一个 create-react-app, 然后在运行, 即可生成一个项目目录:
npx create-react-app my-app
cd my-app
npm start
如此做之后, 就会在my-app下生成一个node.js项目目录, 其中有node_modules, package.json等等很熟悉的文件. 其中package.json中有:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
说明可以来运行一下看看, 使用 npm start
, 然后就会阻塞, 这事因为在后台启动了一个本地服务器:
> my-app@0.1.0 start D:\coding\my-app
> react-scripts start
i 「wds」: Project is running at http://192.168.1.198/
i 「wds」: webpack output is served from
i 「wds」: Content not from webpack is served from D:\coding\my-app\public
i 「wds」: 404s will fallback to /
Starting the development server...
然后会自动弹出来localhost:3000
, 出现React的页面, 会提示Edit src/App.js and save to reload, 也就是编辑App.js就可以来写React应用了. 下边就来看看这个App.js.
简单的例子 默认创建项目的App.js
App.js的内容不多:
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
可以看到, 这其中只有一个函数, App, 然后导入了react, svg和css文件, 这个函数的返回值是用一个小括号包围的一段HTML代码, 但里边很多东西又不太像. 然后再看同一个目录下边的index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
这里的核心就是ReactDOM.render函数, 导入了App函数, 然后渲染了看上去像一个单独的XML标签, 以App作为标签名称的一个片段, 然后去获取#root对应的元素. 最后来看一下页面是什么样子, 在项目的public目录下边找到index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
去掉前边header, 整个body其实就一个标签, 也就是一个id=root的Div标签, 然后将其渲染成了App.js中的那些HTML. 这其实就是一个React应用的雏形. 一般有一个主程序, 一个页面的各个部分, 作为组件被导入, 然后被渲染在指定的位置. 使用WebStorm也可以直接创建ReactApp, 比较方便. 直接打开这个项目目录也可以, 只需要在右上角运行的地方添加一个npm start的运行就可以. npm build就是打包, npm eject是弹出所有内部的代码, 可以看到后台的代码. npm test就是test.
将函数改成类
使用一个函数和类都可以作为模板, 改成类的时候要注意, 必须使用指定名称的render()方法:
import React, {Component} from 'react';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
页面一样可以正常工作, 也就是说对于 <App />这种渲染方式来说, 无论是函数形式还是类形式都可以.
渲染动态内容
在每个类中, 都有state属性, 保存着当前组件所使用的变量, 就和vue的data很像. 可以将类简单修改一下, 在构造器中, 设置this.state, 然后使用{}将其渲染出来:
class App extends Component {
constructor() {
super();
this.state = {
string: 'Hello React!'
}
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>{this.state.string}</p>
<button>Change Text</button>
</header>
</div>
);
}
}
如果渲染多个对象, 则可以使用map方法, 然后返回要渲染的内容, react就会认出来应该渲染多个:
class App extends Component {
constructor() {
super();
this.state = {
monsters: [
{
name: 'Frankenstein',
id: 'asc1'
},
{
name: 'Dracula',
id: 'asc2'
},
{
name: 'Zombie',
id: 'asc3'
},
{
name: 'Frankenstein',
id: 'asc4'
},
],
}
}
render() {
return (
<div className="App">
{
this.state.monsters.map(monster => <h1 key={monster.id}>{monster.name}</h1>)
}
</div>
);
}
}
这里有一个JSX属性是key, 也和vue很类似, 用于标识唯一对应关系, 以及加快渲染速度, 就不用每次都更新整个虚拟DOM.
响应事件
动态Web页面一大好处就是可以互动, 现在来添加一个按钮用于更改显示的文字.
<button onClick={()=>this.setState({string:'saner'})}>Change Text</button>
实际就是点击之后, 将当前组件的state对象更换成一个新的组件, 这样就会渲染出新的内容. 自己尝试了一下发现setState()才能更改对象, 直接自行更改, 比如下边两个, 都是不行的:
<button onClick={() => this.state.string = "gugugug"}>Change Text</button>
<button onClick={() => this.state = {string: "gugugug"}}>Change Text</button>
这个只是简单用法, 之后再慢慢来看新的了, 还有组件之间如何交换数据和事件.
JSX
render()函数中返回的类似于HTML的东西, 其实是一种JSX语言. 注意观察HTML标签上的属性, 像className这种属性, 就是JSX属性而不是html属性, 而像 src={}
, 花括号中的是变量或者表达式, 可以被替换成实际的值. 注意其中的onClick, 是驼峰, 并不是HTML5里的onclick, 所以也不是HTML属性. 所以在JSX中, 可以使用原版的HTML, 也可以使用JSX属性. 这个和Vue也很类似.
组件
对于像例子中, 继承了React.Component的, 就可以认为是一个组件. 所以可以使用类, 构造器, render()方法等. 最重要的是, 可以把组件使用在render()函数中, 将组件名作为一个自闭合标签渲染出来. 这是最重要的. 这样就组成了组件与组件之间的层级关系, 一个页面全部都由组件构成, 组件拥有自己的内部状态.