SpringMVC入门

目录

SpringMVC概述

SpringMVC快速入门

第一步:创建Maven工程,并导入相关的依赖

第二步:创建控制器类

第三步:初始化SpringMVC环境

第四步:创建Tomcat的Servlet容器配置类

第五步:导入tomcat插件,并设置war方式打包

第六步:启动

测试

注意:需要在main目录下面新建一个webapp目录

请求路径优化

指定请求方法

请求参数处理

六种常规类型

第一种:普通请求参数

第二种:pojo类型请求参数

第三种:数组类型请求参数

第四种:List集合类型

第五种:map集合类型

日期请求参数传递

文件类型参数传递

1.先导入依赖

2.编写文件解析器,并交给SringMVC管理(第三方bean)使用注解@Bean

JSON类型参数传递

第一步:导入解析json对象的依赖

第二步:让SpringMVC开启辅助功能,如日期类型转换,json类型转换

第三步:编写Controller类,并使用注解@RequestBody,一个方法只能使用一次(解析前端传来的json对象)

[​编辑 数组类型的pojo类型](#编辑 数组类型的pojo类型)

处理中文请求乱码问题

1.GET请求乱码问题

2.解决POST请求乱码

响应数据

响应一个页面

响应JSON对象,也要使用@Response注解

响应JSON对象数组

RESful风格


SpringMVC概述

MVC(Model View Controller),一种用于创建web应用程序的表现层的模式

1.Model(模型):数据模型,用于封装数据

2.View(视图):页面视图,用于展示数据

  • jsp
  • html

3.Controller(控制器):处理用户交互的调度器,用于根据用户需求处理程序逻辑

SpringMVC快速入门

第一步:创建Maven工程,并导入相关的依赖

springMVC的依赖

html 复制代码
<!--        springMVC的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

servlet-api

注意:需要指定作用范围

html 复制代码
<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
<!--            需要指定作用范围-->
            <scope>provided</scope>
        </dependency>

我们可以发现springMVC的依赖包括了spring-context的依赖

第二步:创建控制器类

java 复制代码
/*
1.需要交给spring管理
2.定义处理请求的方法
3.设置当前方法的访问路径
4.设置返回数据类型为String
 */
@Controller
public class UserController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save");
        return "springMVC";
    }
}

创建控制器类也需要四步:

第一步:需要交给spring管理,即添加**@Controller注解**

第二步:定义处理请求的方法-->public String save()

第三步:设置当前方法的访问路径-->使用注解**@RequestMapping("/save")**

第四步:设置返回数据类型为String-->使用注解@ResponseBody

第三步:初始化SpringMVC环境

这是一个设置扫描范围的配置类(主配置类)

java 复制代码
@Configuration
@ComponentScan("com.hhh")
public class SpringMvcConfig {
}

第四步:创建Tomcat的Servlet容器配置类

java 复制代码
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
    //创建SpringMVC容器(spring容器)
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        //ApplicationContext ctx =new AnnotationConfigApplicationContext();
        //加载配置类,创建SpringMVC容器
        AnnotationConfigWebApplicationContext ctx =new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    //设置哪些请求交给springMVC管理
    @Override
    protected String[] getServletMappings() {
        //这里设置了所有请求都交给SpringMVC管理
        return new String[]{"/"};

    }
    //创建Spring容器
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}

第五步:导入tomcat插件,并设置war方式打包

html 复制代码
 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 指定端口 -->
                    <port>8080</port>
                    <!-- 请求路径 -->
                    <path>/</path>
<!--                    &lt;!&ndash;这个名称需要,在maven插件中显示应用名称&ndash;&gt;-->
<!--                    <server>tomcat7</server>-->
                </configuration>
            </plugin>
        </plugins>
    </build>
html 复制代码
<packaging>war</packaging>

完整pom.xml

html 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hhh</groupId>
    <artifactId>spring_day6_MVC</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
<!--            需要指定作用范围-->
            <scope>provided</scope>
        </dependency>
<!--        springMVC的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 指定端口 -->
                    <port>8080</port>
                    <!-- 请求路径 -->
                    <path>/</path>
<!--                    &lt;!&ndash;这个名称需要,在maven插件中显示应用名称&ndash;&gt;-->
<!--                    <server>tomcat7</server>-->
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

第六步:启动

点击加号,选择maven,然后再Run里填写tomcat7:run,最后点击apply

结果:

测试

启动成功

注意:需要在main目录下面新建一个webapp目录

请求路径优化

添加一个新的类

java 复制代码
@Controller
public class BookController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("book save");
        return "bookSpringMVC";
    }
}

请求路径与之前的一样,会报错

所以这样添加目录

但是这样子每个方法都要添加一级目录,比较麻烦,所以我们可以在这个类上使用注解@RequestMapping注解

java 复制代码
@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("book save");
        return "bookSpringMVC";
    }
}
java 复制代码
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save");
        return "springMVC";
    }
}

测试:

指定请求方法

现在我们使用的式@RequestMapping注解,这个注解支持GET,POST请求,但是我们要指定请求方法要怎么做呢?

java 复制代码
@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping(value = "/save",method = RequestMethod.GET)//这样子只能使用GET请求
    @ResponseBody
    public String save(){
        System.out.println("book save");
        return "bookSpringMVC";
    }
}

请求参数处理

六种常规类型

第一种:普通请求参数

请求参数的key值与方法的形参名一致

后端:

java 复制代码
@Controller
public class ParamController {
    //普通类型参数
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(@RequestParam("name") String username, Integer age){//请求参数名和变量名一致即可
        System.out.println("username="+username);
        System.out.println("age="+age);
        return "CommonParam";
    }

}

使用postman向后端发送请求

如果前端请求参数名字与后端形参名不一致时,使用@RequestParam注解。

SpringMVC会自动把String类型的age转换成Integer类型

第二种:pojo类型请求参数

pojo类的成员变量名字与前端的key值一致

User类

java 复制代码
public class User {
    private String name;
    private Integer age;
    private Address address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
    

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

Address类型

java 复制代码
public class Address {
    private String province;
    private String city;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

后端:

java 复制代码
@Controller
public class ParamController {
  
    //pojo嵌套类型
    @RequestMapping("/pojoContainPojoParam")
    @ResponseBody
    public String pojoContainPojoParam(User user){
        System.out.println(user);
        return "pojoContainPojoParam";
  
}

前端:

可以发现如果成员变量也是pojo类型,就要使用成员变量名.成员变量名的方法

结果:

原理:SpringMVC会使用构造器实例化出一个pojo类对象,即User对象(new User()),然后使用User类里的setXxx()方法进行赋值,如果没有构造器会报错,没有set方法那么这个成员变量就为空null值

如果使用注解@RequestParam

就会报错:

因为**@RequestParam是直接把请求参数与形参进行绑定**,并直接赋值,这样一来User类型对象并没有实例化,所以就会报错

第三种:数组类型请求参数

前端使用多个相同名字的key值与形参变量名一致

java 复制代码
@Controller
public class ParamController {
 
    //数组类型
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[]list){
        System.out.println(Arrays.toString(list));
        return "arrayParam";
    }

}

前端:

结果:

第四种:List集合类型

java 复制代码
@Controller
public class ParamController {
    
    //集合类型
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String>list){
        //因为List不是简单类型,所以springMVC会直接把List看成pojo类型,然后会实例化list,但是List集合没有构造器,就会报错
        //所以添加@RequestParam注解,这样一来spring会直接给list赋值,而不是实例化去使用set()方法
        System.out.println(list);
        return "listParam";
    }
  
}

前端:

可以发现我们后端的形参中使用了@RequestParam注解,因为这个注解的作用 就是绑定 形参变量,直接进行赋值,因为List集合不是简单类型,所以SpringMVC会把List集合看出pojo类型,会先实例化List集合再进行set方法赋值,但是List集合并没有构造器,因此不加@RequestParam注解就会报错:

第五种:map集合类型

java 复制代码
@Controller
public class ParamController {
    //map集合类型
    @RequestMapping("/mapParam")
    @ResponseBody
    public String mapParam(@RequestParam Map<String,String> map){
        //@RequestParam把请求参数与形参绑定,直接赋值
        //System.out.println(map);
        map.forEach((key,value)-> System.out.println(key+"->"+value));
        return "mapParam";
    }
}

前端:

结果:

日期请求参数传递

java 复制代码
@Controller
public class DateController {
    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(Date date){
        System.out.println(date);
        return "dateParam";
    }
}

前端:

结果:

可以发现时期使用的是/来间隔,如果使用-来间隔,会报错:

不能把String类型转换成Date类型,所以我们要使用注解@DateTimeFormat的pattern属性来指定日期类型格式

java 复制代码
@Controller
public class DateController {
    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(Date date,@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1){
        System.out.println(date);
        System.out.println(date1);
        return "dateParam";
    }
}

如果要运行成功,还需要再主配置类中添加@EnableWebMvc,让SpringMVC开启辅助功能

java 复制代码
@Configuration
@ComponentScan("com.hhh")
@EnableWebMvc//让SpringMVC开启辅助功能
public class SpringMvcConfig {
}

结果:

文件类型参数传递

1.先导入依赖

html 复制代码
<!--        文件解析的依赖-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

2.编写文件解析器,并交给SringMVC管理(第三方bean)使用注解@Bean

java 复制代码
@Configuration
@ComponentScan("com.hhh")
@EnableWebMvc//让SpringMVC开启辅助功能
public class SpringMvcConfig {
    //配置文件解析器,并交给SpringMVC管理
    @Bean("multipartResolver")//这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取bean的
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();
        commonsMultipartResolver.setMaxUploadSize(1024*1024);//单位是字节(byte)
        //设置文件最大为1MB
        return  commonsMultipartResolver;
    }
}

注意:这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取这个类型的bean

后端

java 复制代码
@Controller
public class FileController {
    @RequestMapping("/fileParam")
    @ResponseBody
    public String fileParam(MultipartFile file) throws IOException {
        if(!file.isEmpty()){
            file.transferTo(new File("D://test.txt"));//把文件另存为
        }
        return "fileParam";
    }
}

前端

请求方法只能选择post,文件类型要选择form-data,其他类型选择的是右边那个长的

结果:

D盘出现该文件,成功

JSON类型参数传递

第一步:导入解析json对象的依赖

html 复制代码
<!--        解析json的依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>

第二步:让SpringMVC开启辅助功能,如日期类型转换,json类型转换

java 复制代码
@Configuration
@ComponentScan("com.hhh")
@EnableWebMvc//让SpringMVC开启辅助功能,如日期类型转换,json类型转换
public class SpringMvcConfig {
    //配置文件解析器,并交给SpringMVC管理
    @Bean("multipartResolver")//这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取bean的
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();
        commonsMultipartResolver.setMaxUploadSize(1024*1024);//单位是字节(byte)
        //设置文件最大为1MB
        return  commonsMultipartResolver;
    }
}

第三步:编写Controller类,并使用注解@RequestBody,一个方法只能使用一次(解析前端传来的json对象)

java 复制代码
@Controller
public class JsonController {
    @RequestMapping("/pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println(user);
        return "pojoParamForJson";
    }
}

前端

结果:

数组类型的pojo类型

java 复制代码
   @RequestMapping("/arrayPojoParam")
    @ResponseBody
    public String arrayPojoParam(@RequestBody List<User>list){
        System.out.println(list);
        return "arrayPojoParam";
    }

前端

数组使用[]

结果

处理中文请求乱码问题

1.GET请求乱码问题

html 复制代码
   <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 指定端口 -->
                    <port>8080</port>
                    <!-- 请求路径 -->
                    <path>/</path>
<!--                    &lt;!&ndash;这个名称需要,在maven插件中显示应用名称&ndash;&gt;-->
<!--                    <server>tomcat7</server>-->
                    <uriEncoding>utf-8</uriEncoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

添加<uriEncoding>utf-8</uriEncoding>

2.解决POST请求乱码

为web容器添加过滤器并指定字符集

java 复制代码
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
    //创建SpringMVC容器(spring容器)
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        //ApplicationContext ctx =new AnnotationConfigApplicationContext();
        //加载配置类,创建SpringMVC容器
        AnnotationConfigWebApplicationContext ctx =new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    //设置哪些请求交给springMVC管理
    @Override
    protected String[] getServletMappings() {
        //这里设置了所有请求给SpringMVC管理
        return new String[]{"/"};
    }
    //创建Spring容器
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    //设置参数编码为utf-8,解决post请求乱码
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        return new Filter[]{characterEncodingFilter};
    }
}

添加

//设置参数编码为utf-8,解决post请求乱码

@Override

protected Filter[] getServletFilters() {

CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();

characterEncodingFilter.setEncoding("UTF-8");

return new Filter[]{characterEncodingFilter};

}

响应数据

响应一个页面

创建一个jsp文件

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<div>hello</div>
</body>
</html>
java 复制代码
@Controller
public class ResponseController {
    //不加@ResponseBody就会去找页面名为page.jsp的页面
    @RequestMapping("/toPage")
    public String toPage(){
        System.out.println("toPage");
        return "page.jsp";
    }
}

如果加了@ResponseBody

java 复制代码
 @RequestMapping("/toText")
    @ResponseBody
    public String toText(){
        System.out.println("toText");
        return "page.jsp";
    }

返回的就是字符串本身

所以@Response注解(使用在方法上)的作用就是设置当前控制器的返回值作为响应体。

不加这个注解就会去找对应名字的页面,并返回给前端

响应JSON对象,也要使用**@Response注解**

返回类型是对象

java 复制代码
@Controller
public class ResponseController {

    @RequestMapping("/toJson")
    @ResponseBody
    public User toJson(){
        User user = new User();
        user.setName("hhh");
        user.setAge(19);
        Address address = new Address();
        address.setProvince("河北");
        address.setCity("石家庄");
        user.setAddress(address);
        return user;
    }


}

响应JSON对象数组

java 复制代码
@Controller
public class ResponseController {

    @RequestMapping("/toJsonArray")
    @ResponseBody
    public List<User> toJsonArray(){
        User user1 = new User();
        user1.setName("hhh");
        user1.setAge(19);
        Address address = new Address();
        address.setProvince("河北");
        address.setCity("石家庄");
        user1.setAddress(address);

        User user2 = new User();
        user2.setName("aaa");
        user2.setAge(19);
        Address address2 = new Address();
        address2.setProvince("河北");
        address2.setCity("石家庄");
        user2.setAddress(address2);
        List<User>list=new ArrayList<>();
        Collections.addAll(list,user1,user2);
        return list;

    }

}

注意:跟解析请求JSON对象一样,也要导入json解析所需要的依赖,也需要使用注解@EnableWebMvc//让SpringMVC开启辅助功能,如日期类型转换,json类型转换

RESful风格

java 复制代码
@Controller
public class UserController {
    //新增,保存操作
    @RequestMapping(value = "/users",method = RequestMethod.POST)
    @ResponseBody
   public String save(){
       return "save";
   }
   //修改,更新
   @RequestMapping(value = "/users",method = RequestMethod.PUT)
   @ResponseBody
   public String update(){
        return "update";
   }
   //查询全部
    @RequestMapping(value = "/users",method = RequestMethod.GET)
    @ResponseBody
    public String getAll(){
        return "getAll";
    }
    //查询某一个
    @RequestMapping(value = "/users/{id}",method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数
        System.out.println("id="+id);
        return "getById";
    }
    //删除某一个
    @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable("id") Integer id){
        System.out.println("id="+id);
        return "delete";
    }
}

我们可以发现每个@RequestMapping都要写/users,比较麻烦,我们可以直接在类上使用注解 @RequestMapping

每个方法都要写@Response比较麻烦,我们可以直接在类上使用注解 @ResponseBody

java 复制代码
@Controller
@RequestMapping("/users")
@ResponseBody
public class UserController {
    //新增,保存操作
    @RequestMapping(method = RequestMethod.POST)
   public String save(){
       return "save";
   }
   //修改,更新
   @RequestMapping(method = RequestMethod.PUT)
   public String update(){
        return "update";
   }
   //查询全部
    @RequestMapping(method = RequestMethod.GET)
    public String getAll(){
        return "getAll";
    }
    //查询某一个
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数
        System.out.println("id="+id);
        return "getById";
    }
    //删除某一个
    @RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
    public String delete(@PathVariable("id") Integer id){
        System.out.println("id="+id);
        return "delete";
    }
}

然后我们还发现每个@RequsetMapping都要写一个method属性来指定请求方法,比较麻烦,所以,Post请求就使用@PostMapping,以此类推

@ResponseBody和@Controller这两个注解放在一起可以使用@RestController注解来替代

java 复制代码
//@Controller
//@ResponseBody
@RestController
@RequestMapping("/users")
public class UserController {
    //新增,保存操作
    //@RequestMapping(method = RequestMethod.POST)
    @PostMapping
   public String save(){
       return "save";
   }
   //修改,更新
   //@RequestMapping(method = RequestMethod.PUT)
    @PutMapping
   public String update(){
        return "update";
   }
   //查询全部
   // @RequestMapping(method = RequestMethod.GET)
    @GetMapping
    public String getAll(){
        return "getAll";
    }
    //查询某一个
    //@RequestMapping(value = "/{id}",method = RequestMethod.GET)
    @GetMapping("/{id}")
    public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数
        System.out.println("id="+id);
        return "getById";
    }
    //删除某一个
    //@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
    @DeleteMapping("/{id}")
    public String delete(@PathVariable("id") Integer id){
        System.out.println("id="+id);
        return "delete";
    }
}
相关推荐
牛奶2 分钟前
浏览器藏了这么多神器,你居然不知道?
前端·chrome·api
WebInfra7 分钟前
Rspack 2.0 正式发布!
前端·javascript·前端框架
yaodong51812 分钟前
Spring 中使用Mybatis,超详细
spring·tomcat·mybatis
极速蜗牛14 分钟前
Cursor最近变傻了?
前端
splage20 分钟前
Spring Cloud Data Flow 简介
后端·spring·spring cloud
码字小学妹24 分钟前
Claude Opus 4.7 接入指南(2026):国内配置 + xhigh 推理 + 成本计算
前端
小赵同学WoW26 分钟前
插槽【vue2】与 【vue3】对比
前端
代码随想录26 分钟前
Agent大厂面试题汇总:ReAct、Function Calling、MCP、RAG高频问题
前端·react.js·前端框架
前端那点事26 分钟前
Vue响应式原理|从底层实现到面试考点,一文吃透(Vue2+Vue3全解析)
前端·vue.js
walking95728 分钟前
Vite 打包优化终极指南:从 30MB 到 800KB 的性能飞跃
前端·vue.js·vite