hello world

JSX简介

const element = <h1>Hello, world!</h1>;

这个有趣的标签语法既不是字符串也不是 HTML。
它被称为 JSX,是一个 JavaScript 的语法扩展。JSX 可以生成 React “元素”(可以渲染为DOM)。

在JSX中嵌入表达式
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

在 JSX 语法中,你可以在大括号内放置任何有效的 JavaScript 表达式。例如,2 + 2user.firstNameformatName(user) 都是有效的 JavaScript 表达式。

JSX也是一个表达式

也就是说,你可以在 if 语句和 for 循环的代码块中使用 JSX,将 JSX 赋值给变量,把 JSX 当作参数传入,以及从函数中返回 JSX:

function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}
JSX特定属性
  1. 你可以通过使用引号,来将属性值指定为字符串字面量
const element = <div tabIndex="0"></div>;
  1. 也可以使用大括号,来在属性值中插入一个 JavaScript 表达式
const element = <img src={user.avatarUrl}></img>;

在属性中嵌入 JavaScript 表达式时,不要在大括号外面加上引号。你应该仅使用引号(对于字符串值)或大括号(对于表达式)中的一个,对于同一属性不能同时使用这两种符号。

元素渲染

将一个元素渲染为 DOM

想要将一个 React 元素渲染到根 DOM 节点中,只需把它们一起传入 ReactDOM.render()

const element = <h1>Hello, world</h1>;

ReactDOM.render(element, document.getElementById('root'));
更新已渲染的元素

React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。

目前,更新 UI (视图)的方式是创建一个全新的元素,并将其传入 ReactDOM.render()。(重复调用ReactDOM.render()方法)

注:大多数 React 应用只会调用一次 ReactDOM.render()。

React 只更新它需要更新的部分

React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。

组件&props

函数组件和class组件

函数:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

class:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

注:组件名称必须以大写字母开头。

渲染组件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;

ReactDOM.render(
  element,
  document.getElementById('root')
);
props的只读性

下面这个函数则不是纯函数,因为它更改了自己的入参:

function sum(a, b) {
  return a + b;
}

上面这样的函数被称为“纯函数”,因为该函数不会尝试更改入参,且多次调用下相同的入参始终返回相同的结果。

function withdraw(account, amount) {
  account.total -= amount;
}

所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。

state&生命周期

向 class 组件中添加局部的 state

state的位置:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
将生命周期方法添加到 Class 中
// componentDidMount() 方法会在组件已经被渲染到 DOM 中后运行
componentDidMount(){

}

componentWillUnmount(){
    
}
正确地使用 State
  1. state的正确使用:不要直接修改 State
// Correct
this.setState({comment: 'Hello'});

// Wrong
this.state.comment = 'Hello';
  1. State 的更新可能是异步的
// Correct 使用函数
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
  1. State 的更新会被合并 :
  constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }

posts和comments的更新,互不影响。

“自上而下”或是“单向”的数据流。任何的 state 总是所属于特定的组件,而且从该 state 派生的任何数据或 UI 只能影响树中“低于”它们的组件。

事件处理

  1. bind方法 this.fn=this.fn.bind(this) this.fn.bind(this),即:在构造器中绑定。
const domEle = document.getElementById('root');

class Toggle extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            isToggleOn: false,
        }

        this.hanleClick = this.hanleClick.bind(this);
    }

    hanleClick() {
        console.log("this:", this); // 如果没有bind: this = undefined
        this.setState({isToggleOn: !this.state.isToggleOn});
    }

    render() {
        return (
            <div>
                <button onClick={this.hanleClick}>{this.state.isToggleOn ? 'On' : 'Off'}</button>
                // <button onClick={this.hanleClick.bind(this)}>{this.state.isToggleOn ? 'On' : 'Off'}</button>
            </div>
        )
    }
}


ReactDOM.render(
    <Toggle/>,
    domEle
)
  1. 实验性语法。hanleClick = () => {} ,即: public class fields 语法
const domEle = document.getElementById('root');

class Toggle extends React.Component{
    constructor(props){
        super(props);

        this.state={
            isToggleOn:false,
        }

        // this.hanleClick=this.hanleClick.bind(this);
    }

   // 此语法确保 `handleClick` 内的 `this` 已被绑定。
   // 注意: 这是 *实验性* 语法。
    hanleClick = () => { // 如果没有bind的话,可以使用这种方法。
        console.log("this:",this); 
        this.setState({isToggleOn:!this.state.isToggleOn});
    }
    
    render(){
        return (
            <div>
                <button onClick={this.hanleClick}>{this.state.isToggleOn?'On':'Off'}</button>
            </div>
        )
    }
}



ReactDOM.render(
    <Toggle />,
    domEle
)
  1. 在回调中使用箭头函数: onClick={(e)=>this.hanleClick(e)},不推荐使用这种方法。
<button onClick={(e)=>this.hanleClick(e)}>{this.state.isToggleOn ? 'On' : 'Off'}</button>
向事件处理程序传递参数
// 在回调中使用箭头函数
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>


<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

条件渲染

function UserGreeting(props) {
    return <h1>user打招呼了</h1>
}

function GuestGreeting(props) {
    return <h2>访客打招呼了</h2>
}

class Greeting extends React.Component {
    constructor(props) {
        super(props);

        this.state = {};
    }

    render() {
        const isLoggedIn = this.props.isLoggedIn;

        if (isLoggedIn) {
            return <UserGreeting/>
        } else {
            return <GuestGreeting/>
        }
    }
}

ReactDOM.render(
    <Greeting isLoggedIn={false}/>,
    domEle
)
元素变量

你可以使用变量来储存元素。

const domEle = document.getElementById('root');


function UserGreeting(props) {
    return <h2>欢迎回来。</h2>
}

function GuestGreeting(props) {
    return <h2>请登录</h2>
}

function Greeting(props) {
    const isLoggedIn = props.isLoggedIn;

    if (isLoggedIn) {
        return <UserGreeting/>
    }
    return <GuestGreeting/>
}

function LoginButton(props) {
	// 执行父组件的事件
    return (
        <button onClick={props.onClick}> 
            login
        </button>
    )
}

function LogoutButton(props) {
    return (
        <button onClick={props.onClick}>
            logout
        </button>
    )
}


class LoginControl extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            isLoggedIn: true,
        };

        this.handleLogoutClick = this.handleLogoutClick.bind(this);
        this.handleLoginClick = this.handleLoginClick.bind(this);
    }

    handleLogoutClick() {
        this.setState({
            isLoggedIn: false,
        })
    }

    handleLoginClick() {
        this.setState({
            isLoggedIn: true,
        })
    }

    render() {
        const isLoggedIn = this.state.isLoggedIn;
        let button;
        if (isLoggedIn) {
            button = <LogoutButton onClick={this.handleLogoutClick}/>
        } else {
            button = <LoginButton onClick={this.handleLoginClick}/>
        }

        return (
            <div>
                <Greeting isLoggedIn={this.state.isLoggedIn}/>
                {button}
            </div>
        );
    }

}

ReactDOM.render(
    <LoginControl/>,
    domEle
)
与运算符 &&
return (
    <div>
        <h1>你好!</h1>
        {unreadMessage.length>0&&
            <h3>你有{unreadMessage.length}条消息</h3>
        }
    </div>
)

或者:

{
	unreadMessage.length>0 ?
	(<h3>你有{unreadMessage.length}条消息</h3>):
    (null)
}
三目运算符
render() {
    const isLoggedIn = this.state.isLoggedIn;
    let button;
    // if (isLoggedIn) {
    //     button = <LogoutButton onClick={this.handleLogoutClick}/>
    // } else {
    //     button = <LoginButton onClick={this.handleLoginClick}/>
    // }
    
    return (
        <div>
            {/*{button}*/}
            
            {
                isLoggedIn ? (<LogoutButton onClick={this.handleLogoutClick}/>)
                           : (<LoginButton onClick={this.handleLoginClick}/>)
            }
        </div>
    );
}

LogoutButton和LoginButton这两个组件可以合并到一起的。

function LoginButton(props) {
    // 执行父组件的事件
    return (
        <button onClick={props.onClick}>
            {props.isLoggedIn?'登出':'登录'}
        </button>
    )
}

 <LoginButton isLoggedIn={this.state.isLoggedIn} onClick={this.handleLoginClick}/>
阻止组件渲染

在极少数情况下,你可能希望能隐藏组件,即使它已经被其他组件渲染。若要完成此操作,你可以让 render 方法直接返回 null,而不进行任何渲染。

function WarningBanner(props) {
    if(!props.warn){
        return null;
    }
    return (
        <div className="warning">
            warning!
        </div>
    )
}
列表&key
const numbers=[1,2,3,4,5];
// const listItems= numbers.map((number)=><li key={number}>我是第{number}个</li>)

function NumberList(props) {
    const numbers = props.numbers;
    const listItems = numbers.map((number) => <li key={number}>我是第{number}</li>);

    return (
        <ul>
            {listItems}
        </ul>
    )
}

ReactDOM.render(
    <NumberList numbers={numbers}/>,
    domEle
)
key

key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。一个元素的 key 最好是这个元素在列表中拥有的一个独一无二字符串。通常,我们使用数据中的 id 来作为元素的 key:

const listItems = numbers.map((number)=><li key={number.toString()}>我是第{number}1</li>);
用 key 提取组件

元素的 key 只有放在就近的数组上下文中才有意义。

比方说,如果你提取出一个 ListItem 组件,你应该把 key 保留在数组中的这个 <ListItem /> 元素上,而不是放在 ListItem 组件中的 <li> 元素上。

<ListItem key={number.toString()}
          value={number} />
key 只是在兄弟节点之间必须唯一

数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。然而,它们不需要是全局唯一的。当我们生成两个不同的数组时,我们可以使用相同的 key 值:

key 会传递信息给 React ,但不会传递给你的组件。如果你的组件中需要使用 key 属性的值,请用其他属性名显式传递这个值:

const content = posts.map((post) =>
  <Post
    key={post.id}
    id={post.id}
    title={post.title} />
);

表单

input
handleChange(event) {
    console.log("change-e:", event);
    this.setState({value: event.target.value,});
}

handleSubmit(event) {
    console.log("submit-e:", event);
    console.log("submit-val:", this.state.value);
    event.preventDefault();
}

render() {
    return (
        <form onSubmit={this.handleSubmit}>
            <label>名字:<input type="text"
                             value={this.state.value}
                             onChange={this.handleChange}/>
            </label>
            <input type="submit" value="提交"/>
        </form>
    )
}

如果只有value,没有onChange,那么input是只读的。

Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.

对于受控组件来说,每个 state 突变都有一个相关的处理函数。这使得修改或验证用户输入变得简单。例如,如果我们要强制要求所有名称都用大写字母书写,我们可以将 handlechange 改写为:

handleChange(event) {
  this.setState({value: event.target.value.toUpperCase()});
}
textarea

textarea与input是一样的:

class EssayForm extends React.Component {

    constructor(props) {
        super(props);

        this.state = {value: ''};

        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
        console.log("change-event:", event);
        this.setState({value: event.target.value})
    }

    handleSubmit(event) {
        console.log("submit-event:", event);
        console.log("submit-value:", this.state.value);
        event.preventDefault();
    }


    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    文章:
                    <textarea placeholder="请输入"
                              value={this.state.value}
                              onChange={this.handleChange}>

                    </textarea>
                </label>

                <input type="submit" value="提交"/>
            </form>
        )
    }
}
select标签
class FlavorForm extends React.Component {
    constructor(props) {
        super(props);

        this.state = {value: 'coconut'};

        this.handleChange = this.handleChange.bind(this);
        this.handelSubmit = this.handelSubmit.bind(this);
    }


    handleChange(event) {
        this.setState({value: event.target.value});
    }

    handelSubmit(event) {
        console.log("选中的值:", this.state.value);
        event.preventDefault();
    }

    render() {
        return (
            <form onSubmit={this.handelSubmit}>
                <label>
                    选择你喜欢的:
                    <select value={this.state.value} onChange={this.handleChange}>
                        <option value="grapefruit">葡萄柚</option>
                        <option value="lime">酸橙</option>
                        <option value="coconut">椰子</option>
                        <option value="mango">芒果</option>

                    </select>
                </label>

                <input type="submit" value="提交"/>
            </form>
        )
    }

}
处理多个输入

当需要处理多个 input 元素时,我们可以给每个元素添加 name 属性,并让处理函数根据 event.target.name 的值选择要执行的操作。

class Reservation extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            isGoing: true,
            numberOfGuests: 2,
        };

        this.handleChange=this.handleChange.bind(this);
        this.handleSubmit=this.handleSubmit.bind(this);
    }

    handleSubmit(event) {
        console.log("submit-event", event);
        console.log("submit-value", this.state.isGoing,this.state.numberOfGuests);
        event.preventDefault();
    }

    handleChange(event) {
        console.log("change-event:", event,event.target,event.target.checked);
        const target = event.target;
        const value = target.type=='checkbox'?target.checked:target.value;
        const name = target.name;
        console.log("name:",name);

        this.setState({
            [name]:value,
        })

    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    参与:
                    <input type="checkbox"
                           name="isGoing"
                           checked={this.state.isGoing}
                           onChange={this.handleChange}/>
                </label>

                <br/>
                <label>
                    来宾人数:
                    <input type="number"
                           name="numberOfGuests"
                           value={this.state.numberOfGuests}
                           onChange={this.handleChange}/>
                </label>
                <input type="submit" value="提交"/>
            </form>
        )
    }

}

其中:

    this.setState({
      [name]: value
    });

状态提升

通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。

在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”。

props 是只读的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值