欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

js 基本语法,jsx语法和js语法区别

终极管理员 知识笔记 59阅读

文章目录 认识JSX语法JSX是什么为什么Rect选择了JSXJSX书写规范JSX注释编写 JSX的基本使用JSX的事件绑定this绑定问题参数传递问题 JSX的条件渲染常见的条件渲染方式 JSX的列表渲染JSX的原理和本质JSX的本质虚拟DOM的创建过程 案例练习

认识JSX语法

// 1. 定义根组件const element  <div>Hello World</div>// 2. 渲染根组件const root  ReactDOM.createRoot(document.querySelector(#root))root.render(element)

上述代码中element变量的声明右侧赋值的标签语法其实就是一段JSX的语法。

它不是一段字符串因为没有使用引号包裹它看起来是一段HTML元素但是我们能在js中直接给一个变量赋值HTML吗其实是不可以的如果我们将type text/babel 去除掉那么就会出现语法错误。 JSX是什么

JSX是一种JavaScript的语法扩展也在很多地方称之为JavaScript XML因为看起来就是一段XML语法它用于描述我们的UI界面并且其完成可以和JavaScript融合在一起使用它不同于Vue中的模块语法不需要专门学习模块语法中的一些指令比如v-if、v-for、v-bind等

为什么Rect选择了JSX

React认为渲染逻辑本质上与其他UI逻辑存在内在耦合。比如UI需要绑定事件button、a原生等等、比如UI中需要展示数据的状态、比如在某些状态发生改变时又需要改变UI它们之间是密不可分的所以React没有将标记分离到不同的文件中而是将它们组合到了一起这个地方就是组件。

JSX书写规范 JSX的顶层只能有一个根元素所以我们很多时候会在外层包裹一个div元素或者Fragment为了方便阅读我们通常在jsx的外层包裹一个小括号()这样可以方便阅读并且jsx可以进行换行书写JSX中的标签可以是单标签也可以是双标签如果是单标签必须以/>结尾
return (    <div>        <div>            <h2>{message}</h2>        </div>        <div>哈哈哈</div>    </div>)
JSX注释编写
return (    <div>        {/* JSX的注释写法*/}        <h2>{message}</h2>    </div>)
JSX的基本使用

JSX嵌入变量作为子元素

情况一当变量是Number、String、Array类型时可以直接显示情况二当变量是null、undefined、Boolean类型时内容为空 如果希望可以显示null、undefined、Boolean那么需要转成字符串转换的方式有很多比如toString方法、和空字符串拼接、String等方式 情况三Object对象类型不能作为子元素

JSX嵌入表达式

运算表达式三元运算符执行一个函数

JSX绑定属性

比如元素都会有title属性比如img元素会有src属性比如a元素会有href属性比如元素可能需要绑定class比如元素使用内联样式style JSX的事件绑定

如果原生DOM有一个监听事件我们可以如何操作

方式一获取DOM元素添加监听事件方式二在HTML原生中直接绑定onclick

在React中是如何操作呢

React事件的命名采用小驼峰cameClass而不是纯小写我们需要通过{}传入一个事件处理函数这个函数会在事件发生时被执行
<body>  <div idroot></div>  <script typetext/babel>    // 类组件    class App extends React.Component {      // 组件数据      constructor() {        super()        this.state  {          message: Hello World        }      }      // 组件方法      btnClick() {        // 内部完成了两件事        // 1. 将state中的message值修改掉        // 2. 自动重新执行render函数        this.setState({          message: Hello React        })      }      // 渲染内容      render() {        // 简单数据        // return <h2>Hello World</h2>        // 复杂数据        return (          <div>            <h2>{this.state.message}</h2>            <button onClick{this.btnClick.bind(this)}>修改文本</button>          </div>        )      }      // 为什么这里要bind一下? 因为类中的方法中的this默认指向undefined, 所以要将render函数中的this给方法    }    // 将组件渲染到界面上    const container  document.getElementById(root);    const root  ReactDOM.createRoot(container);    root.render(<App />);  </script></body>

这种数据的数据是定义在当前对象的state中的我们可以通过构造函数中的this.state{定义的数据}然后当我们数据发生变化时我们可以调用this.setState来更新数据并且通知React进行update操作在进行update操作时会重新调用render函数并且使用最新的数据来渲染界面。

this绑定问题

上述代码还存在this绑定问题

在事件执行后我们可能需要获取当前类的对象中相关的属性这个时候需要用到this。

在类中直接定义一个函数并且将这个函数绑定到元素的onClick事件上当前这个函数的this指向是谁呢

默认情况下是undefined因为在正常的DOM操作中监听点击监听函数中的this其实是节点对象比如说button对象但是因为React并不是直接渲染成真实DOM我们所编写的button只是一个语法糖它的本质React的Element对象那么在这里发生监听的时候react在执行函数时并没有绑定this默认情况下就是一个undefined。

我们在绑定的函数中可能想要使用当前对象比如执行this.setState函数就必须拿到当前对象的this我们就需要在传入函数时给这个函数直接绑定this

方案一bind给btnClick显式绑定this
// 写法一<button onClick{this.btnClick.bind(this)}>修改文本</button>// 写法二constructor() {  super()  this.state  {    message: Hello World  }  this.btnClick  this.btnClick.bind(this)}
方案二使用ES6 class fields 语法方案三事件监听时传入箭头函数推荐
<body>  <div idroot></div>  <script typetext/babel>    /*    this的四种绑定规则    1. 默认绑定 独立执行     2. 隐式绑定 作为对象中的方法执行    3. 显式绑定 call apply bind    4. new绑定    */    class App extends React.Component {      constructor() {        super()        this.state  {          counter: 100        }      }      btn1Click() {        console.log(btn1Click)        this.setState({ counter: this.state.counter  1 })      }      // 所有实例都会有btn2Click这个字段将一个箭头函数赋值给btn2Click而箭头函数没有this就会去上层作用域中查找找到的是当前类的作用域的this而this正好指向当前实例      btn2Click  () > {        console.log(btn2Click)        this.setState({ counter: this.state.counter  1 })      }      btn3Click  () > {        console.log(btn3Click)        this.setState({ counter: this.state.counter  1 })      }      render() {        return (          <div>            <h2>当前计数{this.state.counter}</h2>            {/*1. this绑定方式一bind绑定*/}            <button onClick{this.btn1Click.bind(this)}>按钮1</button>            {/*2. this绑定方式二ES6 class fields*/}            <button onClick{this.btn2Click}>按钮2</button>            {/*3. this绑定方式三直接传入一个箭头函数(重要)*/}            <button onClick{() > this.btn3Click()}>按钮3</button>            {/*怎么做的形成一个隐式绑定this是当前实例btn3Click作为当前实例的方法被调用*/}          </div>        )      }    }    const container  document.getElementById(root);    const root  ReactDOM.createRoot(container);    root.render(<App />);  </script></body>
参数传递问题 情况一获取event对象 很多时候我们需要拿到event对象来做一些事情比如阻止默认行为那么默认情况下event对象有被直接传入函数就可以获取到event对象 情况二获取更多参数 有更多参数时最好的方式就是传入一个箭头函数主动执行的事件函数并且传入相关的其他参数
<body>  <div idroot></div>  <script typetext/babel>    class App extends React.Component {      constructor() {        super()        this.state  {          counter: 100        }      }      btn1Click(event) {        console.log(btn1Click, event)      }      btn2Click(event, name, age) {        console.log(btn2Click, event, name, age)      }      render() {        return (          <div>            <h2>当前计数{this.state.counter}</h2>            {/*1. event参数的传递 */}            <button onClick{this.btn1Click.bind(this)}>按钮1</button>            <button onClick{(event) > this.btn1Click(event)}>按钮1</button>            {/*2. 额外的参数传递*/}            <button onClick{this.btn2Click.bind(this,)}>按钮2</button>            <button onClick{(event) > this.btn1Click(event, zy, 18)}>按钮2</button>          </div>        )      }    }    const container  document.getElementById(root);    const root  ReactDOM.createRoot(container);    root.render(<App />);  </script></body>
JSX的条件渲染

某些情况下界面的内容会根据不同的情况显示不同的内容或者决定是否渲染某部分内容

在vue中我们会通过指令来控制比如v-if、v-show在React中所有的条件判断都和普通的JavaScript代码一致 常见的条件渲染方式 方式一条件判断语句适合逻辑较多的情况方式二三元运算符适合逻辑比较简单方式三与运算符&&适合如果条件成立渲染某一个组件如果条件不成立什么内容也不渲染
<body>  <div idroot></div>  <script typetext/babel>    class App extends React.Component {      constructor() {        super()        this.state  {          isReady: true        }      }      render() {        const { isReady }  this.state        let showElement  null        if (isReady) {          showElement  <h2>准备开始比赛吧</h2>        } else {          showElement  <h2>请提前做好准备</h2>        }        return (          <div>            {/*1. 方式一根据条件给变量赋值不同的内容*/}            <div>{showElement}</div>            {/*2. 方式二三元运算符*/}            <div>{isReady ? <button>开始战斗</button> : <h3>准备</h3>}</div>            {/*3. 方式三&&逻辑与运算*/}            {/*场景当某一个值有可能为undefined时使用&&进行条件判断*/}            <div>{info && <div>{info.name     info.desc}</div>}</div>          </div >        )      }    }    const container  document.getElementById(root);    const root  ReactDOM.createRoot(container);    root.render(<App />);  </script></body>
JSX的列表渲染

真实开发中我们会从服务器请求到大量数据数据会以列表的形式存储

比如歌手、歌曲、排行榜列表的数据比如商品、购物车、评论列表的数据比如好友消息、动态、联系人列表数据

在React中并没有像Vue模块语法中的v-for指令而且需要我们通过JavaScript代码的方式组织数据转成JSX那到底如何展示列表呢在React中展示列表最多的方式就是使用数组的map高阶函数。很多时候我们在展示一个数据之前需要先对它进行一些处理比如过滤掉一些内容filter函数比如截取数组中的一部分内容slice函数。

<body>  <div idroot></div>  <script typetext/babel>    class App extends React.Component {      constructor() {        super()        this.state  {          students: [            { id: 1, name: zy, score: 99 },            { id: 2, name: lgc, score: 88 },            { id: 3, name: mxy, score: 100 },            { id: 4, name: jack, score: 66 },            { id: 5, name: kobe, score: 92 },          ]        }      }      render() {        const { students }  this.state        return (          <div>            <h2>学生列表数据</h2>            <div classNamelist>              {                //  选出成绩大于90分的人                students.filter(item > item.score > 90).map(item > {                  return (                    <div classNameitem key{item.id}>                      <h2>学号{item.id}</h2>                      <h2>姓名{item.name}</h2>                      <h2>分数{item.score}</h2>                    </div>                  )                })              }            </div>          </div>        )      }    }    const container  document.getElementById(root);    const root  ReactDOM.createRoot(container);    root.render(<App />);  </script></body>
JSX的原理和本质 JSX的本质

实际上jsx仅仅只是React.createElement(component, props, ...children)函数的语法糖所有的jsx最终都会被转换成React.createElement的函数调用

React.createElement需要传递三个参数

参数一type 当前ReactElement的类型如果是标签元素那么就使用字符串表示“div”如果是组件元素那么就直接使用组件的名称 参数二config 所有jsx中的属性都在config中以对象的属性和值的形式存储比如传入className作为元素的class 参数三children 存放在标签中的内容以children数组的方式进行存储如果是多个元素React内部有对它们进行处理 虚拟DOM的创建过程

我们通过React.createElement最终创建出来一个ReactElement对象这个ReactElement对象是什么作用呢React为什么要创建它呢这是因为React利用ReactElement对象组成了一个JavaScript的对象树JavaScript的对象树就是虚拟DOM。

如何查看ReactElement的树结构呢我们可以将之前的就实现返回结果进行打印

jsx-虚拟DOM-真实DOM

案例练习

要求

在界面上以表格的形式显示一些书籍的数据在底部显示书籍的总价格点击或者-可以增加或减少书籍如果为1那么不能继续-点击移除按钮可以将书籍移除当所有书籍移除完毕时显示购物车为空~
<!DOCTYPE html><html><head>  <meta charsetUTF-8 />  <title>购物车</title>  <!-- 添加依赖 -->  <script src  <script src  <!-- babel -->  <script src  <style>    table {      border-collapse: collapse;      text-align: center;    }    thead {      background-color: #f2f2f2;    }    td,    th {      padding: 10px 16px;      border: 1px solid black;    }  </style></head><body>  <div idroot></div>  <script src./data.js></script>  <script typetext/babel>    class App extends React.Component {      constructor() {        super()        this.state  {          books: books        }      }      format(price) {        return   Number(price).toFixed(2);      }      // 方法      increment(index) {        const newBooks  [...this.state.books]        newBooks[index].count  1        this.setState({ books: newBooks })      }      decrement(index) {        const newBooks  [...this.state.books]        newBooks[index].count - 1        this.setState({ books: newBooks })      }      removeItem(index) {        const newBooks  [...this.state.books]        newBooks.splice(index, 1)        this.setState({ books: newBooks })      }      render() {        const { books }  this.state        // 计算总价        let totalPrice  0        for (let i  0; i < books.length; i) {          totalPrice  books[i].count * books[i].price        }        return (          <div>            <table>              <thead>                <tr>                  <th>序号</th>                  <th>书籍名称</th>                  <th>出版日期</th>                  <th>价格</th>                  <th>购买数量</th>                  <th>操作</th>                </tr>              </thead>              <tbody >                {                  books.map((item, index) > {                    return (                      <tr key{item.id}>                        <td>{item.id}</td>                        <td>{item.name}</td>                        <td>{item.data}</td>                        <td>{this.format(item.price)}</td>                        <td>                          <button disabled{item.count < 1} onClick{() > this.decrement(index)}>-</button>                          {item.count}                          <button onClick{() > this.increment(index)}></button>                        </td>                        <td><button onClick{() > this.removeItem(index)}>移除</button></td>                      </tr>                    )                  })                }              </tbody>            </table>            <h1>总价格{this.format(totalPrice)}</h1>          </div>        )      }    }    const container  document.getElementById(root);    const root  ReactDOM.createRoot(container);    root.render(<App />);  </script></body></html>
// data.jsconst books  [    {        id: 1,        name: 《算法导论》,        data: 2006-9,        price: 85.0,        count: 1,    },    {        id: 2,        name: 《UNIX编程艺术》,        data: 2006-9,        price: 59.0,        count: 1,    },    {        id: 3,        name: 《编程珠玑》,        data: 2006-9,        price: 39.0,        count: 1,    },    {        id: 4,        name: 《代码大全》,        data: 2006-9,        price: 128.0,        count: 1,    },];

container);
root.render();

// data.jsconst books  [    {        id: 1,        name: 《算法导论》,        data: 2006-9,        price: 85.0,        count: 1,    },    {        id: 2,        name: 《UNIX编程艺术》,        data: 2006-9,        price: 59.0,        count: 1,    },    {        id: 3,        name: 《编程珠玑》,        data: 2006-9,        price: 39.0,        count: 1,    },    {        id: 4,        name: 《代码大全》,        data: 2006-9,        price: 128.0,        count: 1,    },];
标签:
声明:无特别说明,转载请标明本文来源!