10步打造完美ASP.NET、Web API和控制台应用程序文件夹结构

一、前言

在大型项目中,合理的文件夹结构是项目成功的关键之一。一个好的文件夹结构就像是一座井然有序的图书馆,每一本书(代码文件)都有其固定的位置,让人能迅速找到所需。它可以让团队成员更容易理解和维护代码,减少代码冲突,提高开发效率。想象一下,在一个没有规划的项目里,各种文件杂乱无章地堆砌在一起,新成员加入时,光是弄清楚代码的布局就得花费大量时间,更别提高效开发了。接下来,我们将详细介绍如何在ASP.NET、Web API 和控制台应用程序中组织文件夹结构,带你开启高效编程之旅。

二、ASP.NET文件夹结构组织

2.1 基本文件夹结构

一个典型的ASP.NET项目文件夹结构如下:

复制代码
MyProject/
├── Controllers/
│   ├── HomeController.cs
│   └── AccountController.cs
├── Models/
│   ├── User.cs
│   └── Product.cs
├── Views/
│   ├── Home/
│   │   └── Index.cshtml
│   └── Account/
│       └── Login.cshtml
├── App_Start/
│   ├── RouteConfig.cs
│   └── BundleConfig.cs
├── Filters/
│   └── AuthorizeAttribute.cs
├── Scripts/
│   └── site.js
├── Content/
│   └── site.css
├── Properties/
│   └── launchSettings.json
├── wwwroot/
│   ├── css/
│   ├── js/
│   └── img/
├── App_Data/
│   └── database.mdf
├── Tests/
│   └── UnitTests.cs
├── bin/
└── MyProject.csproj

2.2 详细解释

  • Controllers:存放所有控制器类文件,每个控制器负责处理特定的请求。就好比是餐厅里的服务员,根据客人(用户请求)的不同需求,引导他们到相应的餐桌(处理逻辑),例如HomeController负责处理与首页相关的请求,AccountController则专注于账户相关操作。

  • Models:存放所有模型类文件,模型类用于表示数据结构。可以将其想象成工厂里的模具,定义了产品(数据)的形状和规格,像User模型类对应着用户的数据结构,包含用户的各种属性,如Id、Name、Email等。

  • Views:存放所有视图文件,每个视图文件对应一个控制器的操作。它是用户直接看到的界面,如同舞台上的表演,不同的场景(视图)由对应的演员(控制器操作)触发,比如Home控制器的Index操作对应的视图文件Index.cshtml,用于展示首页的内容。

  • App_Start:存放应用程序启动时需要初始化的配置文件,如路由配置和捆绑配置。这就像是汽车的启动装置,在启动时要设定好行驶路线(路由)以及资源的加载方式(捆绑),确保应用程序能按照预定的规则运行。

  • Filters:存放过滤器类文件,用于处理请求和响应的预处理和后处理。类似于安检门,在请求进入和响应出去之前进行检查和过滤,比如AuthorizeAttribute过滤器可以用于验证用户是否有权限访问某些资源。

  • Scripts:存放 JavaScript 文件。这些文件为网页增添动态交互效果,如同魔术师手中的道具,让页面变得更加生动有趣,site.js可能包含页面的一些特效、表单验证等交互逻辑。

  • Content:存放 CSS 文件和其他静态资源。它决定了网页的外观样式,就像化妆师为演员化妆,通过site.css等文件设置字体、颜色、布局等,让页面美观大方。

  • Properties:存放项目属性文件,如launchSettings.json。这是项目的 "身份证",记录了项目启动的相关设置,如开发环境下的端口号等信息。

  • wwwroot:存放静态文件,如图片、JavaScript 和 CSS 文件。这里是网页的素材库,浏览器可以直接访问其中的资源,为页面提供丰富的视觉和交互元素。

  • App_Data:存放数据库文件和其他数据文件。相当于仓库,存储着应用程序运行所需的数据,如database.mdf是数据库文件,存放着用户信息、业务数据等。

  • Tests:存放单元测试文件。这是项目的质检员,通过编写各种测试用例,对代码的各个模块进行检测,确保代码质量,如UnitTests.cs可以对控制器、模型等进行功能测试。

  • bin:存放编译后的输出文件。是代码编译后的 "成品区",编译好的程序集等文件存放在这里,供运行时使用。

  • MyProject.csproj:项目的配置文件。它是项目的 "管家",管理着项目的依赖项、编译选项、引用的库等信息,确保项目能够正确构建和运行。

2.3 示例代码

以下是部分关键代码示例:

复制代码
using System.Web.Mvc;
namespace MyProject.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
    }
}

这段代码定义了一个名为HomeController的控制器,它继承自Controller基类,有一个Index方法,当用户访问应用程序的根路径(对应Home控制器的Index操作)时,该方法返回对应的视图。

复制代码
namespace MyProject.Models
{
    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
    }
}

这里定义了一个User模型类,包含Id、Name、Email三个属性,用于表示用户的数据结构,在应用程序的不同层之间传递用户相关的数据。

复制代码
@model MyProject.Models.User
@{
    ViewBag.Title = "Home Page";
}
<h1>Welcome, @Model.Name!</h1>
<p>Email: @Model.Email</p>

这是Views/Home/Index.cshtml视图文件的部分代码,通过@model指令指定该视图使用的模型为MyProject.Models.User,然后在页面中展示了用户的姓名和邮箱信息,实现了数据从模型到视图的展示。

三、Web API 文件夹结构组织

3.1 基本文件夹结构

一个典型的 Web API 项目文件夹结构如下:

复制代码
MyWebApi/
├── Controllers/
│   ├── UsersController.cs
│   └── ProductsController.cs
├── Models/
│   ├── User.cs
│   └── Product.cs
├── DTOs/
│   ├── UserDto.cs
│   └── ProductDto.cs
├── Services/
│   ├── UserService.cs
│   └── ProductService.cs
├── Repositories/
│   ├── UserRepository.cs
│   └── ProductRepository.cs
├── Interfaces/
│   ├── IUserService.cs
│   └── IProductService.cs
├── Migrations/
│   └── InitialCreate.cs
├── App_Start/
│   ├── WebApiConfig.cs
│   └── FilterConfig.cs
├── Filters/
│   └── ValidateModelAttribute.cs
├── Helpers/
│   └── Utility.cs
├── Properties/
│   └── launchSettings.json
├── wwwroot/
│   ├── css/
│   ├── js/
│   └── img/
├── Tests/
│   └── UnitTests.cs
├── bin/
└── MyWebApi.csproj

3.2 详细解释

  • Controllers:存放所有 API 控制器类文件,每个控制器负责处理特定的 API 请求。就像是交通枢纽的调度员,根据不同的路线请求(API 请求),指引车辆(数据)去往相应的目的地,例如UsersController处理与用户相关的 API 操作,像获取用户列表、查询单个用户信息等。

  • Models:存放所有模型类文件,模型类用于表示数据结构。如同建筑蓝图,定义了数据的架构,User模型类规定了用户数据有哪些字段,如Id、Name、Email等,为数据的存储和传输提供了模板。

  • DTOs:存放数据传输对象(DTO)类文件,用于在客户端和服务器之间传输数据。可以把它想象成快递包裹,将服务器端的数据精心打包,按照客户端能够理解的方式进行封装,避免直接暴露内部复杂的数据结构,UserDto可能只包含客户端需要展示的用户部分信息,减少不必要的数据传输。

  • Services:存放业务逻辑类文件,每个服务类负责处理特定的业务逻辑。这是项目的 "智囊团",例如UserService包含了用户注册、登录验证、用户信息修改等业务逻辑,将复杂的业务规则封装在其中,使得控制器能专注于请求处理。

  • Repositories:存放数据访问类文件,每个仓库类负责与数据库进行交互。相当于数据库的 "管家",UserRepository负责执行与用户数据相关的数据库操作,如查询用户、插入新用户、更新用户信息等,将数据库操作细节封装起来,提高代码的可维护性。

  • Interfaces:存放接口文件,用于定义服务和仓库的契约。就像是电器的插头标准,确保不同组件之间能够正确连接和交互,IUserService接口定义了UserService应该实现的方法,让依赖注入等机制能更方便地管理组件间的关系。

  • Migrations:存放数据库迁移文件,用于管理数据库 schema 的变化。好比是城市的规划变更记录,随着项目发展,数据库结构可能需要调整,迁移文件记录了从一个版本到另一个版本的数据库结构变化过程,方便团队协作和版本管理。

  • App_Start:存放应用程序启动时需要初始化的配置文件,如路由配置和过滤器配置。这是项目启动的 "导航仪",WebApiConfig.cs配置 API 的路由规则,确保请求能准确找到对应的控制器和操作方法,FilterConfig.cs设置过滤器,对请求和响应进行预处理和后处理。

  • Filters:存放过滤器类文件,用于处理请求和响应的预处理和后处理。类似工厂的质检环节,在数据流入流出时进行检查和过滤,ValidateModelAttribute过滤器可以验证传入 API 的数据是否符合模型定义,若不符合则提前返回错误信息,避免无效数据进入业务逻辑层。

  • Helpers:存放辅助类文件,用于提供常用的工具方法。如同工具箱,里面装着各种实用工具,Utility类可能包含一些通用的字符串处理、日期处理等方法,供项目的其他部分复用,提高开发效率。

  • Properties:存放项目属性文件,如launchSettings.json。这是项目的 "配置档案",记录了项目启动的环境设置,如开发环境下运行的端口号、是否启用调试等信息。

  • wwwroot:存放静态文件,如图片、JavaScript 和 CSS 文件。这里是 Web API 对外展示的 "橱窗",虽然 Web API 主要侧重于数据接口,但有时也可能需要提供一些静态资源,如接口文档的样式文件等,浏览器可以直接访问其中的资源。

  • Tests:存放单元测试文件。这是项目的 "体检中心",针对各个组件编写测试用例,确保UsersController的每个 API 方法、UserService的业务逻辑、UserRepository的数据访问等都能正常工作,保障项目质量。

  • bin:存放编译后的输出文件。是代码编译后的 "成品区",编译好的程序集等文件存放在这里,供运行时使用。

  • MyWebApi.csproj:项目的配置文件。它是项目的 "管家",管理着项目的依赖项、编译选项、引用的库等信息,确保项目能够正确构建和运行。

3.3 示例代码

以下是部分关键代码示例:

复制代码
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using MyWebApi.Models;
using MyWebApi.Services;
namespace MyWebApi.Controllers
{
    public class UsersController : ApiController
    {
        private readonly IUserService _userService;
        public UsersController(IUserService userService)
        {
            _userService = userService;
        }
        // GET: api/Users
        public IEnumerable<User> Get()
        {
            return _userService.GetAllUsers();
        }
        // GET: api/Users/5
        public User Get(int id)
        {
            return _userService.GetUserById(id);
        }
        // POST: api/Users
        public void Post([FromBody]User user)
        {
            _userService.AddUser(user);
        }
        // PUT: api/Users/5
        public void Put(int id, [FromBody]User user)
        {
            _userService.UpdateUser(id, user);
        }
        // DELETE: api/Users/5
        public void Delete(int id)
        {
            _userService.DeleteUser(id);
        }
    }
}

这段UsersController代码继承自ApiController,通过依赖注入获取IUserService实例,然后根据不同的 HTTP 请求方法(GET、POST、PUT、DELETE),调用对应的UserService方法来处理用户数据的查询、新增、更新和删除操作。例如,Get方法用于获取所有用户列表,当客户端发送GET请求到api/Users路径时,会返回所有用户信息。

复制代码
using System.Collections.Generic;
using MyWebApi.Models;
namespace MyWebApi.Services
{
    public interface IUserService
    {
        IEnumerable<User> GetAllUsers();
        User GetUserById(int id);
        void AddUser(User user);
        void UpdateUser(int id, User user);
        void DeleteUser(int id);
    }
}

IUserService接口定义了用户服务应该具备的方法,这是一种契约,确保实现该接口的类(如UserService)必须提供这些方法的具体实现,使得代码的依赖关系更加清晰,便于维护和扩展。

复制代码
using System.Collections.Generic;
using System.Linq;
using MyWebApi.Models;
namespace MyWebApi.Services
{
    public class UserService : IUserService
    {
        private readonly List<User> _users = new List<User>
        {
            new User { Id = 1, Name = "Alice", Email = "alice@example.com" },
            new User { Id = 2, Name = "Bob", Email = "bob@example.com" }
        };
        public IEnumerable<User> GetAllUsers()
        {
            return _users;
        }
        public User GetUserById(int id)
        {
            return _users.FirstOrDefault(u => u.Id == id);
        }
        public void AddUser(User user)
        {
            user.Id = _users.Max(u => u.Id) + 1;
            _users.Add(user);
        }
        public void UpdateUser(int id, User user)
        {
            var existingUser = _users.FirstOrDefault(u => u.Id == id);
            if (existingUser!= null)
            {
                existingUser.Name = user.Name;
                existingUser.Email = user.Email;
            }
        }
        public void DeleteUser(int id)
        {
            var userToDelete = _users.FirstOrDefault(u => u.Id == id);
            if (userToDelete!= null)
            {
                _users.Remove(userToDelete);
            }
        }
    }
}

UserService类实现了IUserService接口,内部使用一个简单的List模拟数据库存储用户数据。GetAllUsers方法返回所有用户列表,GetUserById根据传入的id查找并返回对应的用户,AddUser向列表中添加新用户并分配唯一Id,UpdateUser更新指定id用户的信息,DeleteUser删除指定id的用户,这些方法体现了对用户数据的基本业务操作逻辑。

四、控制台应用程序文件夹结构组织

复制代码
MyConsoleApp/
├── Program.cs
├── Models/
│   ├── User.cs
│   └── Product.cs
├── Services/
│   ├── UserService.cs
│   └── ProductService.cs
├── Repositories/
│   ├── UserRepository.cs
│   └── ProductRepository.cs
├── Interfaces/
│   ├── IUserService.cs
│   └── IProductService.cs
├── Helpers/
│   └── Utility.cs
├── Config/
│   └── appsettings.json
├── Logs/
│   └── log.txt
├── Tests/
│   └── UnitTests.cs
├── bin/
└── MyConsoleApp.csproj

4.2 详细解释

  • Program.cs:项目的入口文件,包含Main方法。它就像是一场音乐会的指挥家,是整个控制台应用程序启动的起点,程序从这里开始按部就班地执行,在Main方法里可以初始化各种服务、加载配置,然后调用相应的业务逻辑。

  • Models:存放所有模型类文件,模型类用于表示数据结构。类似于建筑的基石,定义了数据的基本形态,User模型类描述了用户数据的构成,有哪些字段,为数据在程序中的流转提供了统一的模板。

  • Services:存放业务逻辑类文件,每个服务类负责处理特定的业务逻辑。这是项目的 "大脑中枢",UserService负责处理用户相关的业务,如用户注册、登录验证、信息修改等复杂操作,将业务规则封装在其中,使得程序的逻辑清晰,易于维护。

  • Repositories:存放数据访问类文件,每个仓库类负责与数据库进行交互。相当于数据库的 "搬运工",UserRepository负责从数据库中获取用户数据、将新用户数据存入数据库、更新或删除用户数据等操作,把数据库操作细节隐藏起来,提高代码的可维护性和可测试性。

  • Interfaces:存放接口文件,用于定义服务和仓库的契约。就像是不同设备之间的接口标准,确保服务类和仓库类能够按照统一的规范进行交互,IUserService接口规定了UserService应该实现的方法,方便进行依赖注入等操作,让代码结构更加灵活。

  • Helpers:存放辅助类文件,用于提供常用的工具方法。如同工具箱里的各种工具,Utility类可能包含一些文件读写、字符串处理、日期格式化等通用方法,供项目的其他部分复用,避免重复造轮子,提高开发效率。

  • Config:存放配置文件,如appsettings.json。这是项目的 "配置宝库",可以配置数据库连接字符串、日志级别、应用程序的一些运行参数等,使得应用程序在不同环境下能够灵活运行,通过修改配置文件,无需改动代码就能调整程序的行为。

  • Logs:存放日志文件。它是程序运行的 "日记本",记录着程序运行过程中的关键信息,如错误信息、重要操作的记录等,方便在出现问题时排查故障,了解程序的运行轨迹,log.txt里详细记录着每一次的异常、警告以及一些关键业务的执行情况。

  • Tests:存放单元测试文件。这是项目的 "质检员",针对各个组件编写测试用例,确保UserService的业务逻辑正确、UserRepository的数据访问无误等,保障项目质量,就像对产品的各个零部件进行严格检测,只有通过测试的代码才能进入正式的运行环境。

  • bin:存放编译后的输出文件。是代码编译后的 "成品区",编译好的程序集等文件存放在这里,供运行时使用,当程序启动时,会从这里加载可执行文件,让程序跑起来。

  • MyConsoleApp.csproj:项目的配置文件。它是项目的 "管家",管理着项目的依赖项、编译选项、引用的库等信息,确保项目能够正确构建和运行,比如引入外部的数据库驱动库、日志框架等依赖,都要在这个文件里进行配置。

4.3 示例代码

以下是部分关键代码示例:

复制代码
using System;
using MyConsoleApp.Services;
namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var userService = new UserService();
            var users = userService.GetAllUsers();
            Console.WriteLine("Users:");
            foreach (var user in users)
            {
                Console.WriteLine($"Name: {user.Name}, Email: {user.Email}");
            }
        }
    }
}

这段Program.cs代码是控制台应用程序的入口,在Main方法中,首先实例化UserService,然后调用其GetAllUsers方法获取所有用户信息,并将用户的姓名和邮箱打印到控制台,展示了从服务获取数据并进行简单输出的过程。

复制代码
using System.Collections.Generic;
using MyConsoleApp.Models;
namespace MyConsoleApp.Services
{
    public interface IUserService
    {
        IEnumerable<User> GetAllUsers();
    }
}

IUserService接口定义了用户服务应该具备的获取所有用户的方法,为服务类的实现提供了统一的契约,使得其他组件可以依赖这个接口进行编程,而不用担心具体的实现细节。

复制代码
using System.Collections.Generic;
using MyConsoleApp.Models;
namespace MyConsoleApp.Services
{
    public class UserService : IUserService
    {
        private readonly List<User> _users = new List<User>
        {
            new User { Id = 1, Name = "Alice", Email = "alice@example.com" },
            new User { Id = 2, Name = "Bob", Email = "bob@example.com" }
        };
        public IEnumerable<User> GetAllUsers()
        {
            return _users;
        }
    }
}

UserService类实现了IUserService接口,内部使用一个简单的List模拟数据库存储用户数据,GetAllUsers方法返回这个列表,模拟从数据库获取所有用户数据的操作,体现了业务逻辑层对数据的处理和提供对外接口的功能。

五、打造完美文件夹结构的 10 个通用步骤

5.1 明确项目需求与架构

在着手构建文件夹结构之前,要对项目需求进行全方位剖析。比如开发一个电商项目,需考虑商品展示、用户购物流程、支付体系、订单管理等功能模块。依据项目规模,判断是小型创业项目快速迭代,还是大型企业级应用严谨架构;考虑团队协作模式,是分布式团队远程协作,还是集中办公紧密沟通。基于这些确定项目架构,如采用经典的三层架构(表现层、业务逻辑层、数据访问层),还是微服务架构将功能拆分为多个独立服务,为后续文件夹规划奠定基础。

5.2 按职责划分文件夹

依据代码功能分类创建文件夹,这是让项目井然有序的关键。数据模型相关代码统一归入 "Models" 文件夹,它如同建筑蓝图,定义了数据的结构,像用户模型、商品模型等。业务逻辑放入 "Services" 文件夹,这里是项目的 "智囊团",处理订单创建、用户注册登录等复杂业务。数据访问操作集中在 "Repositories" 文件夹,负责与数据库对接,执行数据的增删改查。如此一来,开发人员能迅速定位所需代码,如在电商项目中找商品数据操作,直奔 "Repositories" 下与商品相关类。

5.3 规范文件夹命名

统一、表意清晰的命名规则至关重要。文件夹名采用复数形式,清晰表明其包含内容,如 "Controllers""Models"。遵循通用命名习惯,配置文件放 "Config",辅助工具类放 "Helpers",避免使用晦涩难懂缩写或随意名称。在团队协作时,新成员看到规范命名就能快速领会文件夹用途,减少沟通成本,提升开发效率。

5.4 分离关注点

每个文件夹应专注单一职责,杜绝代码混杂。"Controllers" 只处理请求转发与响应,不涉及业务逻辑细节;"Models" 纯粹定义数据结构,不含业务规则。以博客系统为例,文章控制器只负责接收用户对文章的操作请求,将数据传递给服务层处理,不操心文章数据如何存储,保持职责纯粹,后续维护升级时,能迅速定位问题代码,修改一处不影响其他功能。

5.5 合理规划层级

采用浅层扁平结构,避免文件夹层级过深。一般三层左右为宜,如项目根目录下一级是功能模块文件夹,再下一级是对应功能的具体分类文件夹。过深层级会让文件查找困难,像在多层嵌套找一个特定工具类,犹如大海捞针。合理层级让代码导航便捷,开发人员能快速在相关层级找到目标文件。

5.6 处理静态文件

针对不同程序类型妥善安排静态文件位置。在ASP.NET中,图片、JavaScript、CSS 等静态文件放 "wwwroot" 文件夹,浏览器可直接访问,便于前端页面渲染。Web API 虽主要提供数据接口,但有时也需静态资源,类似处理,将相关文件规整存放,确保访问顺畅,如接口文档的样式文件放对应位置,提升接口可读性。

5.7 管理配置文件

将配置文件集中存放,便于统一管理与维护。ASP.NET的应用程序启动配置放 "App_Start",包含路由、捆绑配置等;控制台应用程序的配置,如数据库连接字符串、日志级别设置,放 "Config" 文件夹下的 "appsettings.json"。开发不同环境(开发、测试、生产)时,能便捷切换配置,避免因配置散落各处导致遗漏或错误。

5.8 重视测试文件夹

专门设立 "Tests" 文件夹存放测试文件,涵盖单元测试、集成测试等。测试是项目质量保障,为代码编写配套测试用例,如对 Web API 的控制器方法测试请求响应正确性,对业务逻辑类测试复杂业务规则。持续运行测试,能及时发现代码变更引入的问题,保障项目稳定可靠,每次代码提交前跑一遍测试,确保新功能不破坏原有功能。

5.9 持续优化调整

项目在迭代开发中,需求变更、技术升级不可避免,文件夹结构要随之优化。依据代码异味、团队反馈,如某个文件夹文件过多过杂,需重新拆分;发现新功能模块与现有结构不契合,及时调整布局。定期回顾结构合理性,让文件夹结构始终适配项目发展,保持代码库健康。

5.10 团队协作与沟通

团队成员务必遵循统一文件夹结构规范,这是项目有序推进的基石。新成员加入时,安排培训讲解结构要点;开发过程中,若对结构有分歧或改进建议,及时沟通交流。利用版本控制系统提交说明、团队会议等,确保大家理解并遵守结构约定,避免个人随意变更导致混乱,让文件夹结构有效落地,助力项目成功。

六、总结

ASP.NET、Web API 和控制台应用程序开发中,合理的文件夹结构是项目成功的基石。ASP.NET项目通过清晰划分控制器、模型、视图等文件夹,让 Web 应用开发有条不紊;Web API 项目借助专门的 DTOs、Repositories 等文件夹,高效处理数据交互与业务逻辑;控制台应用程序虽结构相对简洁,但合理布局模型、服务、配置等文件夹同样关键。遵循本文的 10 个步骤,明确需求、规范命名、分离职责、重视测试并持续优化,能让代码可读性、可维护性大幅提升,减少团队协作的摩擦。希望大家将这些方法运用到实际项目,打造出结构精良的应用程序,开启高效编程之旅。

相关推荐
an317429 分钟前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
utmhikari11 分钟前
【日常随笔】深入回答纯Vibe Coding写后端项目的几个问题
后端·ai编程·vibecoding
尚早立志21 分钟前
Spring Boot 源码研读之ConfigurableEnvironment 环境准备
java·spring boot·后端
谢尔登24 分钟前
【React】 状态管理方案
前端·react.js·前端框架
用户21366100357243 分钟前
Vue商品详情与放大镜组件
前端·javascript
半个落月1 小时前
从Tapas小Demo理清localStorage、事件与this
前端·javascript
李明卫杭州1 小时前
Vue2 中 v-model 处理不同数据结构的技巧
前端·javascript·vue.js
李明卫杭州1 小时前
使用 computed 处理 v-model 复杂数据结构
前端·javascript·vue.js
布朗克1681 小时前
Go 入门到精通-08-复合类型之数组与切片
开发语言·后端·golang·数组与切片
fliter1 小时前
从手写 HTTP/1.1 到拆开 HTTP/2
后端