组件声明和jsx

React学习

快速创建一个项目

首先用vite + react启动一个react-ts项目

1
2
3
pnpm create vite [项目名称] --template react-ts

pnpm create vite react-starter --template react-ts
添加一些依赖
  • unocss
  • antfu eslint
  • lodash-es |325x332

删除多余的内容,仅保留App.tsx和main.tsx

组件

组件声明

JSX必须有一个根节点

可以是 <></> // 这是一个 Fragment

所有html标签必须结束

不管是单标签还是双标签都必须结束

JSX requires tags to be explicitly closed: self-closing tags like <img> must become <img />, and wrapping tags like <li>oranges must be written as <li>oranges</li>.

大部分react 的东西都使用 驼峰。

比如绑定事件 onClick

比如添加class = className

1
2
3
4
5
6
7
export default function Page() {
    return (
        <>
            <h1>Home</h1>
        </>
    )
}

导出,用ES6语法,导出一个函数返回一个JSX片段。

注意:不要在组件内部再去申明一个组件。

注意:react组件的使用需要开头大写,这样来区分原生的html标签。

1
2
3
4
5
6
7
export default function Gallery() {
  // 🔴 Never define a component inside another component!
  function Profile() {
    // ...
  }
  // ...
}

导出和导入组件

可以先看这篇熟悉一下导入导出,是一样的。

ES导入导出语法

具名导出
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 导出
export function MyCard(props: { name: string }) {  // 接收props
  return <div>{props.name}</div>;
}

// 在page里导入和使用
import {MyCard} from '../components/MyCard';
export default function Page() {
    return (
        <>
            <MyCard name="Hello" />
        </>
    )
}
默认导出
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 默认导出
export default function MyButton(props: { text: string }) {
    return <button>{props.text}</button>
}

// 默认导入
import MyButton from "../components/MyButton.tsx";
export default function Page() {
    return (
        <>
            <MyButton text="click" />
        </>
    )
}

JSX|TSX 动态插入内容、属性

绑定变量属性

title={name}的这种形式去给一个标签添加动态的属性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function App()  {  
	const name = 'foo'
	return(
		 <div title={name}> /** 使用属性*/
			{name}
		</div>
	)
}
// 一个花括号里面输入来使用js表达式和变量

// 导出组件
export default App
绑定class

直接添加class和绑定class的变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

function App() {  

const myClassName: string = 'w-10 h-10 bg-blue-6'

  return (  
    <>      /** 这里使用了一对空标签当成根标签*/
	    /** 直接绑定class */
     <div className="w-2"></div>  
	    /** 绑定class变量 */
     <div className={myClassName}></div>
    </>  
)}  
  
export default App
绑定style
1
2
3
4
5
6
7
8
9
function App() {  
  const styleObj = {  
    backgroundColor: 'red',  
  }  return (  
    <>      <div style={styleObj}></div>  
      <div style={{ color: 'red' }}></div>  
    </>  )}  
  
export default App
总结

动态绑定class和style

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
export default function page() {
  const name = 'foo'
  const classList = 'w-10 h-10'
  const styleObj = {
    backgroundColor: 'red',
  }
  const active = true
  const activeClass = `${active ? 'active' : ''}`

  return (
    <>
      <div className={classList}>{name}</div>
      <div className="bg-blue-5 w-10 h-10"></div>
      <div style={{ background: 'red' }}></div>
      <div style={styleObj}></div>
      <div className={activeClass}></div>
      <div className={`${active}?'active':''`}></div>
      <div className={['test'].join(' ')}></div>
    </>
  )
}
事件操作,获取事件对象event
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 事件操作
function App() {  
    function test(number1?: number, event?: React.FormEvent<HTMLButtonElement>) {  
        console.log(number1, event)  
    }  
  /** React.FormEvent<HTMLButtonElement> react的一些ts类型 */
    return (  
        <div>  
            {/*调用方式1*/}  
            {/*bind方式拿到event,默认最后一个参数就是event*/}  
            <button onClick={test.bind(null, 123)}>  
            </button>  
            {/*调用方式2*/}  
            <button onClick={() => {  
                test(123)  
            }}></button>  
            {/* 箭头函数拿到click事件对象,箭头函数传参就是event*/}  
            <button onClick={(event) => {  
                test(123, event)  
            }}></button>  
        </div>  
    )  
}  
  
export default App

实现html循环遍历

使用map来返回jsx片段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
export function mapRender() {
  const arr = [1, 2, 3]

  const users: userDto[] = [
    {
      name: 'foo',
      age: 18,
    },
    {
      name: 'bar',
      age: 19,
    },
    {
      name: 'zhang san',
      age: 20,
    },
  ]
  interface userDto { name: string, age: number }
  function UserCard({ user }: { user: userDto }) {
    return (
      <>
        <div>
          <h3>
            name:
            {user.name}
          </h3>
          <h4>
            age:
            {user.age}
          </h4>
        </div>
      </>
    )
  }

  return (
    <>
      <div>
        {arr.map((item) => {
          return <div key={item}>{item}</div>
        })}
      </div>

      <div>
        <ul>
          {users.map(user => (
            <li key={user.name}>{user.name}</li>
          ))}
        </ul>
      </div>

      <div>
        <ul>
          {users.map(user => (
            <UserCard key={user.name} user={user} />
          ))}
        </ul>
      </div>

    </>
  )
}
动态添加item
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
export function mapTest2() {
  const [items, setItems] = useState(['React', 'Vue', 'Angular'])

  const addItem = () => {
    setItems([...items, `New Item ${items.length + 1}`])
  }

  return (
    <div>
      <button onClick={addItem}>添加项</button>
      <ul>
        {items.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  )
}

条件渲染

v-if 渲染

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

export function ifTest() {
  const [show, setShow] = useState(true)

  return (
    <div>
      <button onClick={() => setShow(!show)}>toggle</button>
      {show && <div>show</div>}
    </div>
  )
}

添加内联样式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 添加内联样式  
const style1 = {  
    width: '100px',  
    height: '100px',  
    backgroundColor: 'lightskyblue'  
}  
  
const style2 = {  
    width: 200  
}  
  
/**  
 * 媒体查询 + 伪类使用 radium包裹  
 */  
  
function App() {  
    return (  
        <div>  
            <div style={{backgroundColor: 'lightskyblue', width: '100px', height: '50px'}}></div>  
            <div style={style1}></div>  
            <div style={{...style1,...style2}}></div>  
        </div>  
    )  
}  
  
export default App

添加外部css文件

1
import './index.css'
1
2
3
4
5
6
7
8

/** index.css**/

.box1 {  
    width: 100px;  
    height: 100px;  
    background-color: lightskyblue;  
}
1
2
3
4
5
6
7
8
// 外源css的使用
function App() {  
    return (  
        <div className={ 'box1' }></div>  
    )  
}  
  
export default App

总结

单个花括号和两个花括号

{} {{}}

单个花括号

使用场景:

单个花括号的使用场景有且只有在 tag里面的属性或者是tag包裹的内容

在单个花括号里面开启js的内容。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
export function test(){
    const testClass = 'input-wrapper'
    const content = <div>123</div>
    return (
        <>
            <input type="text" className={testClass}/>
            <div>{content}</div>
        </>
    )
}
两个花括号

绑定内联css

style 绑定一个对象。

所以其实两个花括号 = jsx的js域然后里面放一个对象

等同于我创建一个obj然后用单个花括号绑定进去

1
<div style={{width:"100px", height:"100px",backgroundColor:"red" }}></div>
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy