React基础,Vue也基础

44 阅读7分钟

本文主要对比总结Rect和Vue一些非常基础的用法,如视图层语法,引用JS变量,类名\内联样式,条件\列表渲染,事件处理的最基础的用法。

本文成文时React最新版本是19.2,Vue最新版本是3.5.22。

组件式开发

原生前端开发中,HTML\CSS\JS通常分为多文件编写,除非非常简单的项目会写在一个文件。

当要修改或复用页面某一部分时,需要去多个文件中查找对应部分的HTML/CSS/JS。

即使将HTML/CSS/JS写在一个文件,也是代码堆叠在一起,难以将某一部分抽取出来复用。

而React和Vue都支持将页面拆分为独立的组件文件,便于复用和修改。

React组件文件通常以.jsx为后缀,Vue则使用.vue单文件组件。

组件结构

React函数组件

React当前主流是函数式组件,即组件就是JS函数.

function MyComponent(){
    // ...
}

Vue单文件组件

Vue组件文件以单文件组件(SFC,Single-File Component)为典型形式,文件结构由三个核心标签<template> <script> <style>组成。

  • <template>编写组件的HTML结构(视图模板)
  • <script>编写组件的JS逻辑(数据、方法等)
  • <style>编写组件的CSS样式
<template>
<!-- 视图模板 -->
</template>
<script>
/* 组件逻辑 */
</script>
<style>
/* 组件样式 */
</style>

视图层语法

React和Vue在视图层的核心差异,体现在React使用JSX(JS XML),而Vue使用Template(模板)。

React和Vue标志性的差别既是JSX和Template的区别。

JSX

JSX是一种将HTML嵌入JS的语法扩展,如果是函数组件则通过JS函数返回HTML来描述视图。

function App(){
    return <h1>Hello React!</h1>
}

Template

Template(模板),一种基于HTML的声明式语法,通过在<template>标签内书写HTML来描述视图。

<template>
    <h1>Hello Vue!</h1>
</template>

引用JS变量和字面量

JSX中引用JS变量

React的JSX语法无论是元素内容还是元素属性值都通过{}单大括号引用JS变量。

function MyComponent(){
    let content = '稀土掘金' // 元素内容
    let href = 'https://juejin.cn/' // 元素的href属性值
    return (
        <a href={href}>{content}</div>
    )
}

Template中引用JS变量

Vue的Template中元素内容可以通过{{}}双大括号引用JS变量。

元素属性值需要用""引号包裹引用的JS变量,还需要使用v-bind指令(指令是Template语法的特殊属性,用于在Template中嵌入逻辑)绑定变量,并且JS变量需要在script中声明。

v-bind可以缩写为:

<template>
    <!-- 注:要动态绑定href,如果不使用:href而是href="href" -->
    <!-- 则会把"href"作为字符串字面量传递给href属性和原生HTML一样 --> 
    <a :href="href">{{content}}</a>
</template>
<script setup>
    let content = '稀土掘金' // 元素内容
    let href = 'https://juejin.cn/' // 元素的href属性值
</script>

引用JS字面量

另外React和Vue引用JS字面量和上述引用JS变量的语法是一样的。

类名样式

React className

React通过JSX语法的className属性支持类名样式。

className属性可以使用引号传入字符串,或使用{}大括号传入JS表达式。(注:原生样式类名是class属性,React为了和原生区分采用了className)

className传入字符串

function App(){
    return (
        <h1 className="title">
            <style>{`.title { background-color: #798 }`}</style>
            Hello React!
        </h1>
    )
}

有时候我们需要组件根据某个变量的值(或者说状态)来变换样式,这时可以通过className传入JS表达式来实现,如className根据isActive的值来确定类名是否添加active

function App(){
    // 这里isActive声明为变量
    // 是因为我们还没学到useState
    // 通过手动修改isActive为false测试一下样式根据变量变化
    let isActive = true
    return (
        // className传入三元表达式,根据isActive的值确定是否添加active
        <h1 className={isActive ? 'active' : ''}>
            <style>{`.active{background-color: #798}`}
            Hello React!
        </h1>
    )
}

Vue绑定class

Vue的Template语法是基于HTML,可以直接使用原生HTML元素class属性。

<template>
    <h1 class="title">Hello Vue!</h1>
</template>
<style>
    .title {
        background-color: #579
    }
</style>

但原生class只支持字符串,Vue的Template语法支持class绑定JS对象/数组,需要使用v-bind指令。

v-bind可以缩写为:

  • class绑定JS对象
<template>
    <!-- 注:这里{}大括号外用""引号包裹,看起来像字符串,但其实传入的是JS对象 -->
    <!-- 这是因为Template是扩展HTML,要求属性值用引号包裹 -->
    <h1 :class="{active:isActive}">Hello Vue!</h1>
</template>
<script>
    // 注:Template使用了变量isActive,需要在这声明
    let isActive = true
</script>
<style>
    .active {
        background-color: #798
    }
</style>
  • class绑定JS数组

通常元素的class可能不只一个,class绑定JS数组则可以绑定多个类名

<template>
    <!-- 注:数组内元素要带''引号,如果不带引号则被认为是变量 -->
    <!-- 如下 isActive是变量需要在script中声明 -->
    <h1 :class = "['title', isActive ? 'active' : '']"> Hello Vue! </h1>
</template>
<script>
    let isActive = true
</script>
<style>
    .title {
        color: #567
    }
    .active {
        background-color: #798
    }
</style>

内联样式

React style

React通过JSX语法的style属性支持内联样式。

style属性必须传入一个JS对象,而且是样式对象。

原生内联样式如下面的代码

<h1 style="background-color:#798">Vanilla</h1>

但在JS中对象键名不能直接使用带有横线的样式名,有两种键名命名方式:

  • 驼峰式命名(推荐使用)
  • 引号包裹带横线样式名

如 background-color 样式属性就需要使用 backgroundColor 或 'background-color'作为键名。

function App(){
    return (
        // 注:外侧{}是JSX使用JS变量需要的,内侧{}是JS对象的
        <h1 style={{backgroundColor:'#798'}}>
            Hello React!
        </h1>
        <h1 style={{'background-color':'#579'}}>
            Hello React!
        </h1>
    )
}

Vue:style

Vue通过v-bind:style支持内联样式,style可以传入字符串、对象或数组。

  • style传入字符串
<template>
    <!-- 注:外侧双引号是元素属性值必须使用引号包裹,内侧单引号标识这是一个字符串 -->
    <h1 :style="'background-color: #798;color: #567'">Hello Vue!</h1>
</template>
  • style传入对象(推荐)
<template>
    <!-- 注:带有横线的对象键名要使用引号包裹 -->
    <h1 :style="{'background-color':'#798',color:'#567'}">Hello Vue!</h1>
</template>
  • style传入数组 当需要传入多个样式对象,可以使用样式数组
<template>
    <h1 :style="[baseStyles, dynamicStyles]">Hello Vue!</h1>
</template>
<script setup>
    let baseStyles = {
        'background-color': '#798'
    }
    let dynamicStyles = {
        color: '#567'
    }
</script>

条件渲染

条件渲染是很常见的UI需求,比如登录前显示登录按钮,登录后显示用户名。

React条件渲染

React的JSX语法可以直接是使用原生JS语法的if/else语句支持条件渲染。(注:React的JSX语法是扩展JS所以也可以使用switch/case语句,但通常使用if/else语句即可)

function MyLogin(){
    // 手动isLogin改为true测试
    let isLogin = false
    let username = 'lee'
    if(isLogin) {
        return (
            <span>{username}</span>
        )
    } else {
        return (
            <button>login</button>
        )
    }
}

Vue条件渲染

Vue的template语法支持v-if指令来实现条件渲染。

<template>
    <span v-if="isLogin">{{username}}</span>
    <button v-else>login</button>
</template>
<script setup>
    // 将isLogin改为true测试
    let isLogin = false
    let username = 'lee'
</script>

列表渲染

列表渲染也是很常见的需求,假设我有一个学生姓名、年龄组成的对象数组。

const students = [
    {name: 'lilei', age: 12},
    {name: 'hanmeimei', age: 13}
]

将数组按照name:xx | age:xx展示,可以使用列表渲染。

React列表渲染

React的JSX语法可以使用JS中所有能生成迭代结果的语句或方法(比如:for循环、while循环、forEach、for...in、for...of等等),但最推荐的是数组的map方法。

JS中map方法会返回一个新数组,如果把列表UI看成一个由HTML元素组成的数组,那么map用于列表渲染再合适不过。

function StudentList(){
    const students = [
        {name:'lilei', age: 12},
        {name:'hanmeimei', age: 13}
    ]
    return (
        <table>
          <tr>
            <th>name</th>
            <th>age</th>
          </tr>
          {students.map((student) => (
            <tr>
              <td>{student.name}</td>
              <td>{student.age}</td>
            </tr>
          ))}
        </table>
    )
}

Vue列表渲染

在Vue中通常使用v-for指令支持列表渲染。

<template>
    <table>
        <tr>
            <th>name</th>
            <th>age</th>
        </tr>
        <tr v-for="student in students">
            <td>{{student.name}}</td>
            <td>{{student.age}}</td>
        <tr>
    </table>
</template>
<script setup>
    const students = [
        {name:'lilei', age: 12},
        {name:'hanmeimei', age: 13}
    ]
</script>

事件绑定

React事件绑定直接采用 “小驼峰命名法” 的属性形式,例如将原生 HTML 的 onclick 改为 onClickonchange 改为 onChange 等,事件处理函数直接通过大括号 {} 传入(本质是传递函数引用)。

Vue通过 v-on 指令(简写为 @)绑定事件,事件名直接使用原生 HTML 的全小写形式(如 clickchange),事件处理函数通过引号包裹的形式指定(引用 Vue 实例中的方法)。

对比原生事件绑定

<button onclick="alert('按钮被点击了')">click me!</button>

在Vue中

<button @click="alert('按钮被点击了')">click me!</button>

在React中

function Button(){
    return (
        <button onClick={()=>alert('按钮被点击了'}>click me!</button>
    )
}