企业项目实训---培训机构教务管理系统技术博客--Second

后端:使用springsecurity技术和使用jwt实现前后端分离的权限验证,使用swagger接口技术,使用redis作为缓存技术。

前端:使用axios进行前后端交互,使用element-plus作为规范页面并且美化页面,使用vue-router作为路由页面的跳转,使用vuex作为页面的状态管理,使用webpack作为打包软件。

使用swagger接口技术—–详细代码实现

Swagger 是一个用于描述、生产、消费 RESTful API 的工具集。它包括了一个开源的规范和一系列的实现,可以帮助开发者设计、构建、文档化和测试 RESTful API。

下面是在 Spring Boot 中使用 Swagger 技术的详细代码实现:

添加依赖

首先,在 pom.xml 文件中添加以下依赖:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
  <version>2.9.2</version>
</dependency>
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger-ui</artifactId>
  <version>2.9.2</version>
</dependency>

配置 Swagger

然后,在配置类中添加 Swagger 相关的配置信息。下面是一个简单的配置类示例:

package com.chun.permission.config;
​
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
​
import java.util.ArrayList;
​
/**
 * @author: zzc
 * @Date: 2023/04/23/15:42
 * @description: Swagger的配置类
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket getDocket(Environment environment){
        // 设置要显示的Swagger环境
        // Profiles.of("pro", "test");
        // 获取项目环境
        boolean flag = environment.acceptsProfiles(Profiles.of("dev", "test"));
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("培训机构教务管理系统文档")
                .enable(flag)
                .select()
                // 以下修改成自己项目对应的controller路径
                .apis(RequestHandlerSelectors.basePackage("com.chun.permission.controller"))
                .build();
    }
    // 配置Swagger文档信息= apiInfo
    private ApiInfo apiInfo(){
        // 作者信息
        Contact contact = new Contact("第八组", "", "15707688226@163.com");
        // Swagger文档信息
        return new ApiInfo(
                "培训机构教务管理系统接口文档",
                "培训机构教务管理系统接口定义",
                "1.0",
                "",
                contact,
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSES-2.0",
                new ArrayList()
        );
    }
}

上面的代码中,我们使用 @EnableSwagger2 注解启用 Swagger,并创建了一个 Docket Bean 来配置 Swagger。在 Docket 的构造器中,我们使用 RequestHandlerSelectors.basePackage 和 PathSelectors.any 方法来指定要扫描的控制器和路径。在最后,我们还添加了一个 ApiInfo 对象来描述 API 的标题、描述和版本号等信息。

添加注解

接着,在控制器类或方法上添加一些 Swagger 的注解,来帮助生成 API 文档。下面是一些常用的注解:

  • @Api:描述该类的作用。

  • @ApiOperation:描述接口的作用和用法。

package com.chun.permission.controller;
​
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chun.permission.common.constant.Constant;
import com.chun.permission.entity.PageBean;
import com.chun.permission.entity.SysRole;
import com.chun.permission.entity.SysUser;
import com.chun.permission.entity.SysUserRole;
import com.chun.permission.service.SysRoleService;
import com.chun.permission.service.SysUserRoleService;
import com.chun.permission.service.SysUserService;
import com.chun.permission.utils.DateUtil;
import com.chun.permission.utils.R;
import com.chun.permission.utils.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
​
import java.io.File;
import java.util.*;
​
/**
 * @Author: zzc
 * @Date: 2023/4/21-20:20
 * @Description: 用户controller控制器
 **/
@RestController
@Api(tags = "系统用户相关接口")
@RequestMapping("/sys/user")
public class SysUserController {
    @Autowired
    private SysUserService sysUserService;
​
    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;
​
    @Value("${avatarImagesFilePath}")
    private String avatarImagesFilePath;
​
    @Autowired
    private SysRoleService sysRoleService;
​
    @Autowired
    private SysUserRoleService sysUserRoleService;
    /**
     * 添加或者修改个人信息
     * @param sysUser
     * @return
     */
    @PostMapping(value = "/save")
    @ApiOperation("添加或者修改个人信息")
    // 表示有这个权限的才可以调用该方法
    @PreAuthorize("hasAuthority('system:user:add')" + "||" + "hasAuthority('system:user:edit')")
    public R save(@RequestBody SysUser sysUser){
        if(sysUser.getId() == null || sysUser.getId() == -1){
            // 获取不到内容
            sysUser.setCreateTime(new Date());
            sysUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getPassword()));
            sysUserService.save(sysUser);
        } else {
            // 有东西
            sysUser.setUpdateTime(new Date());
            sysUserService.updateById(sysUser);
        }
        return R.ok();
    }
​
    /**
     * 修改个人密码
     * @param sysUser
     * @return
     */
    @PostMapping(value = "/updateUserPwd")
    @ApiOperation("修改个人密码")
    // 表示有这个权限的才可以调用该方法
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R updateUserPwd(@RequestBody SysUser sysUser){
        SysUser currentUser = sysUserService.getById(sysUser.getId());
        // 匹配密码
        if(bCryptPasswordEncoder.matches(sysUser.getOldPassword(), currentUser.getPassword())){
            currentUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getNewPassword()));
            currentUser.setUpdateTime(new Date());
            sysUserService.updateById(currentUser);
            return R.ok();
        } else {
            return R.error("输入旧密码错误");
        }
    }
​
    /**
     * 修改用户头像
     * @param sysUser
     * @return
     */
    @PostMapping("/updateAvatar")
    @ApiOperation("修改用户头像")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R updateAvatar(@RequestBody SysUser sysUser){
        SysUser currentUser = sysUserService.getById(sysUser.getId());
        currentUser.setAvatar(sysUser.getAvatar());
        sysUserService.updateById(currentUser);
        return R.ok();
    }
​
    /**
     * 上传用户头像图片
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/uploadImage")
    @ApiOperation("上传用户头像图片")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public Map<String,Object> uploadImage(MultipartFile file)throws Exception{
        Map<String,Object> resultMap=new HashMap<>();
        if(!file.isEmpty()){
            // 获取文件名和后缀,用于拼接新的文件名
            String originalFilename = file.getOriginalFilename();
            String suffixName=originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFileName= DateUtil.getCurrentDateStr()+suffixName;
            FileUtils.copyInputStreamToFile(file.getInputStream(),new File(avatarImagesFilePath + newFileName));
            resultMap.put("code",0);
            resultMap.put("msg","上传成功");
            Map<String,Object> dataMap = new HashMap<>();
            dataMap.put("title",newFileName);
            dataMap.put("src","image/userAvatar/" + newFileName);
            resultMap.put("data", dataMap);
        }
        return resultMap;
    }
​
    /**
     * 根据条件分页查询用户信息
     * @param pageBean
     * @return
     */
    @PostMapping("/list")
    @ApiOperation("根据条件分页查询用户信息")
    @PreAuthorize("hasAuthority('system:user:query')")
    public R list(@RequestBody PageBean pageBean){
        // 去掉空格
        String query = pageBean.getQuery().trim();
​
        Page<SysUser> pageResult = sysUserService.page(
                new Page<>(pageBean.getPageNum(), pageBean.getPageSize()),
                new QueryWrapper<SysUser>().like(StringUtil.isNotEmpty(query),"username",query)
        );
        List<SysUser> userList = pageResult.getRecords();
        // 给每个用户遍历角色
        for (SysUser user : userList){
            List<SysRole> roleList = sysRoleService.list(new QueryWrapper<SysRole>()
                    .inSql("id", "select role_id from sys_user_role where user_id = " + user.getId()));
            user.setSysRoleList(roleList);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("userList", userList);
        resultMap.put("total", pageResult.getTotal());
        return R.ok(resultMap);
    }
​
    /**
     * 验证用户名
     * @param sysUser
     * @return
     */
    @PostMapping("/checkUserName")
    @ApiOperation("验证用户名")
    @PreAuthorize("hasAuthority('system:user:query')")
    public R checkUserName(@RequestBody SysUser sysUser){
        if(sysUserService.getByUsername(sysUser.getUsername()) == null){
            return R.ok();
        }else{
            return R.error();
        }
    }
​
    /**
     * 根据id查询
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询")
    @PreAuthorize("hasAuthority('system:user:query')")
    public R findById(@PathVariable(value = "id") Integer id){
        SysUser sysUser = sysUserService.getById(id);
        Map<String,Object> map=new HashMap<>();
        map.put("sysUser",sysUser);
        return R.ok(map);
    }
​
​
    /**
     * 删除用户(包括批量删除)
     * @param ids
     * @return
     */
    @Transactional
    @PostMapping("/delete")
    @ApiOperation("删除用户(包括批量删除)")
    @PreAuthorize("hasAuthority('system:user:delete')")
    public R delete(@RequestBody Long[] ids){
        sysUserService.removeByIds(Arrays.asList(ids));
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>()
                .in("user_id", ids));
        return R.ok();
    }
​
    /**
     * 重置密码
     * @param id
     * @return
     */
    @GetMapping("/resetPassword/{id}")
    @ApiOperation("重置密码")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R resetPassword(@PathVariable(value = "id")Integer id){
        SysUser sysUser = sysUserService.getById(id);
        sysUser.setPassword(bCryptPasswordEncoder.encode(Constant.DEFAULT_PASSWORD));
        sysUser.setUpdateTime(new Date());
        sysUserService.updateById(sysUser);
        return R.ok();
    }
​
    /**
     * 更新status状态
     * @param id  用户id
     * @param status 想要更新的状态0[正常]/1[封禁]
     * @return
     */
    @GetMapping("/updateStatus/{id}/status/{status}")
    @ApiOperation("更新status状态")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R updateStatus(@PathVariable(value = "id")Integer id,
                          @PathVariable(value = "status")String status){
        SysUser sysUser = sysUserService.getById(id);
        sysUser.setStatus(status);
        sysUserService.saveOrUpdate(sysUser);
//        redisUtil.removeByPrex(Constant.AUTHORITY_KEY);
        return R.ok();
    }
​
    /**
     * 用户角色授权
     * @param userId 用户id
     * @param roleIds 用户角色id数组
     * @return
     */
    @Transactional
    @PostMapping("/grantRole/{userId}")
    @ApiOperation("用户角色授权")
    @PreAuthorize("hasAuthority('system:user:role')")
    public R grantRole(@PathVariable("userId") Long userId,@RequestBody Long[] roleIds){
        List<SysUserRole> userRoleList=new ArrayList<>();
        Arrays.stream(roleIds).forEach(r -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setRoleId(r);
            sysUserRole.setUserId(userId);
            userRoleList.add(sysUserRole);
        });
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        sysUserRoleService.saveBatch(userRoleList);
//        redisUtil.removeByPrex(Constant.AUTHORITY_KEY);
        return R.ok();
    }
}
​

在上面的示例中,我们使用了 @ApiOperation 注解来描述"添加或者修改个人信息"、"修改个人密码"、"修改用户头像"、"上传用户头像图片"、"根据条件分页查询用户信息"、"验证用户名"、"根据id查询"、"删除用户(包括批量删除)"、"重置密码"、"更新status状态"、"用户角色授权"这几个接口的作用和用法。

访问 Swagger UI

最后,在浏览器中访问 http://{localhost:8866/swagger-ui.html,就可以看到自动生成的 API 文档页面了。在这个页面上,我们可以查看所有可访问的 API 接口,并测试它们的响应结果。

使用Redis作为缓存技术—–详细代码实现

在项目中使用 Redis 作为缓存技术有以下优点:

高性能:Redis 是一款高性能的内存数据库,具有极快的读写速度和响应时间。因此,使用 Redis 作为缓存可以大大提升系统的性能。

可扩展性:Redis 支持分布式部署,能够通过集群来实现数据的横向扩展,从而满足大规模系统的需求。

数据类型丰富:Redis 支持多种数据结构,例如字符串、哈希表、列表、集合等,支持更灵活的数据处理方式。

持久化功能:Redis 支持数据的持久化,可以将内存中的数据保存到磁盘上,以便在服务器重启后能够恢复数据。

高可用性:Redis 支持主从复制、哨兵机制和集群模式,能够保证数据的高可用性和可靠性。

丰富的生态系统:Redis 生态系统非常丰富,有许多基于 Redis 的开源产品和框架,例如缓存工具 Spring Cache、消息队列 RedisMQ 等。

以下是在 Spring Boot 中使用 Redis 作为缓存技术的详细代码实现。

添加 Redis Starter 依赖

首先需要添加 Redis Starter 依赖到 pom.xml 文件中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置 Redis 连接参数

在 application.properties 或 application.yml 文件中配置 Redis 连接参数:

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=123456

创建 RedisTemplate 对象

在 Spring Boot 中通过 RedisTemplate 对象来操作 Redis 缓存。需要创建一个 RedisConfig 类,用于创建 RedisTemplate 对象,并将其注入到 Spring 容器中:

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }
}

使用 RedisTemplate 操作 Redis 缓存

在需要使用 Redis 缓存的地方注入 RedisTemplate 对象,然后调用其方法即可对 Redis 进行操作。例如:

java复制代码@Service
public class UserServiceImpl implements UserService {
​
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
​
    @Override
    public User getUserById(Long id) {
        String key = "user:" + id;
        // 先从缓存中获取用户信息
        User user = (User) redisTemplate.opsForValue().get(key);
        if (user == null) {
            // 缓存中不存在用户信息,则从数据库中获取
            user = userRepository.findById(id).orElse(null);
            if (user != null) {
                // 将用户信息缓存到 Redis 中
                redisTemplate.opsForValue().set(key, user);
            }
        }
        return user;
    }
​
    @Override
    public void deleteUserById(Long id) {
        String key = "user:" + id;
        // 从缓存中删除用户信息
        redisTemplate.delete(key);
        // 从数据库中删除用户信息
        userRepository.deleteById(id);
    }
}

以上代码实现了通过 Redis 缓存机制来获取和删除用户信息。在 getUserById 方法中,首先从 Redis 缓存中获取用户信息,如果缓存中不存在,则从数据库中获取,并将其缓存到 Redis 中;在 deleteUserById 方法中则直接从缓存和数据库中删除用户信息。

后端使用springsecurity技术和使用jwt实现前后端分离的权限验证,前端使用axios进行与后端交互——详细代码实现

我们正在构建一个基于 Vue.js 和 Spring Boot 的应用程序,并使用 JWT 令牌和 Spring Security 来实现前后端分离的权限验证。下面是从我们项目中截取出来的一些代码,并写成一个简单的例子,通过这个例子来说明如何将这些技术组合在一起。

后端配置

首先,我们需要配置 Spring Security 来处理 JWT 令牌并验证用户的身份。为此,我们可以创建一个 SecurityConfig 类,并进行以下配置(此处省略添加依赖的步骤,默认依赖已经添加进pom.xml文件中):

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Autowired
    private JwtTokenProvider jwtTokenProvider;
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置不需要认证的路径
        http.authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .anyRequest().authenticated();
 
        // 禁用CSRF防护
        http.csrf().disable();
 
        // 添加JWT过滤器
        http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
 
        // 其他配置项...
    }
 
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12);
    }
}

上面的代码中,我们设置了哪些路径不需要认证,通过调用JwtTokenFilterConfigurer将jwtTokenProvider传递给JwtTokenFilter过滤器,将会在每个请求到达控制器之前执行。

接下来,我们需要创建一个JwtTokenProvider类来生成和验证JWT令牌。下面是一个简单的示例:

@Component
public class JwtTokenProvider {
 
    private static final Logger logger = LoggerFactory.getLogger(JwtTokenProvider.class);
 
    @Value("${jwt.secret}")
    private String jwtSecret;
 
    @Value("${jwt.expirationInMs}")
    private int jwtExpirationInMs;
 
    public String generateToken(Authentication authentication) {
        UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
 
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + jwtExpirationInMs);
 
        return Jwts.builder()
                .setSubject(Long.toString(userPrincipal.getId()))
                .setIssuedAt(new Date())
                .setExpiration(expiryDate)
                .signWith(SignatureAlgorithm.HS512, jwtSecret)
                .compact();
    }
 
    public Long getUserIdFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(jwtSecret)
                .parseClaimsJws(token)
                .getBody();
 
        return Long.parseLong(claims.getSubject());
    }
 
    public boolean validateToken(String authToken) {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
            return true;
        } catch (SignatureException ex) {
            logger.error("Invalid JWT signature");
        } catch (MalformedJwtException ex) {
            logger.error("Invalid JWT token");
        } catch (ExpiredJwtException ex) {
            logger.error("Expired JWT token");
        } catch (UnsupportedJwtException ex) {
            logger.error("Unsupported JWT token");
        } catch (IllegalArgumentException ex) {
            logger.error("JWT claims string is empty.");
        }
        return false;
    }
}

在这个例子中,我们使用了 JJWT 库来创建和解析 JWT 令牌,并使用 jwtSecret 和 jwtExpirationInMs 属性来设置签名密钥和过期时间。

前端配置

在前端,我们需要使用 axios 进行 HTTP 请求,并将 JWT 令牌作为请求头信息发送到后端。下面是一个简单的 Vue.js 组件示例:

<template>
    <div>
        <!-- 登录表单 -->
        <form>
            <input type="text" v-model="username">
            <input type="password" v-model="password">
            <button @click.prevent="login">登录</button>
        </form>
 
        <!-- 显示用户信息 -->
        <div v-if="user">
            <p>用户ID:{{ user.id }}</p>
            <p>用户名:{{ user.username }}</p>
        </div>
    </div>
</template>
 
<script>
import axios from 'axios';
 
export default {
    data() {
        return {
            username: '',
            password: '',
            user: null,
            token: null
        };
    },
    methods: {
        async login() {
            try {
                const response = await axios.post('/api/auth/login', {
                  username: this.username,
                  password: this.password
                  });
            // 将JWT令牌保存在本地存储中
            localStorage.setItem('jwtToken', response.data.token);

            // 使用axios拦截器,在每个请求之前添加Authorization头信息
            axios.interceptors.request.use(
                config => {
                    const token = localStorage.getItem('jwtToken');
                    if (token) {
                        config.headers['Authorization'] = `Bearer ${token}`;
                    }
                    return config;
                },
                error => {
                    return Promise.reject(error);
                }
            );

            // 从后端获取用户信息
            const userResponse = await axios.get('/api/user/me');
            this.user = userResponse.data;
        } catch (error) {
            console.error(error);
        }
    }
},
async created() {
    try {
        // 从本地存储中获取JWT令牌并验证其有效性
        const token = localStorage.getItem('jwtToken');
        if (token && jwtDecode(token).exp > Date.now() / 1000) {
            axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;

            // 从后端获取用户信息
            const response = await axios.get('/api/user/me');
            this.user = response.data;
        }
    } catch (error) {
        console.error(error);
    }
	}
};
</script>

在这个例子中,我们使用了 axios 库来进行 HTTP 请求,并添加了一个拦截器来在每个请求之前添加 JWT 令牌。我们还将 JWT 令牌保存在本地存储中,以便在下一次访问应用程序时可以使用它。当组件被创建时,我们还检查本地存储中是否存在有效的 JWT 令牌,并从后端获取用户信息。

总结一下,使用 Spring Security 技术和 JWT 令牌实现前后端分离的权限验证是一种非常流行的技术架构。这种架构可以有效地提高应用程序的安全性和可靠性,并使前端和后端开发团队可以独立进行工作。

使用element-plus作为规范页面并且美化页面

使用 Element Plus 作为前端 Vue 的规范页面并且美化页面有以下优点:

快速开发:Element Plus 提供了大量的基础组件和样式,可以帮助开发人员快速搭建 UI 界面,提高开发效率。

统一规范:Element Plus 遵循一致的设计规范和风格,可以使得页面具有良好的视觉效果,并且能够达到统一的体验标准。

自定义样式:Element Plus 支持自定义样式,可以根据项目需求来进行修改和调整,以满足不同的业务需求。

易于维护:使用 Element Plus 规范了页面之后,可以使得代码易于维护和管理。同时,组件库也会不断更新和维护,保证应用程序与时俱进。

社区支持:Element Plus 是一个广受欢迎的开源组件库,拥有庞大的社区和活跃的贡献者,可以及时解决问题和提供技术支持。

综上所述,使用 Element Plus 作为前端 Vue 的规范页面并且美化页面可以提高开发效率、统一界面风格、支持自定义样式、易于维护和得到社区支持等优点,是一种非常有效的开发方式。Element Plus 是一款基于 Vue 3 的 UI 组件库,提供了多种组件和样式,可用于快速开发美观的 Web 应用程序。以下是一个简单的示例,演示如何在 Vue 中使用 Element Plus。

安装 Element Plus

首先需要安装 Element Plus 组件库。可以通过 npm 命令来进行安装:

npm install element-plus

引入 Element Plus 组件

在需要使用 Element Plus 组件的 Vue 单文件组件中,引入需要使用的组件。例如,需要使用 ElButtonElInput 组件,可以通过以下方式引入:

<template>
  <div>
    <el-input placeholder="请输入关键字" v-model="keyword"></el-input>
    <el-button type="primary" @click="search">搜索</el-button>
  </div>
</template>

<script>
import { ElButton, ElInput } from 'element-plus';

export default {
  components: { ElButton, ElInput },
  data() {
    return {
      keyword: '',
    };
  },
  methods: {
    search() {
      // 处理搜索逻辑
    },
  },
};
</script>

在上面的代码中,通过 import 语句引入 ElButtonElInput 组件,并在 components 属性中注册这两个组件。然后在模板中使用这两个组件,并绑定相关事件和数据。

样式自定义

可以通过修改组件的 props 属性来自定义其样式。例如,如果需要修改 ElButton 组件的颜色和字体大小,可以通过以下方式实现:

<template>
  <div>
    <el-button type="primary" size="medium" :style="{ backgroundColor: '#f00', fontSize: '16px' }">提交</el-button>
  </div>
</template>

<script>
import { ElButton } from 'element-plus';

export default {
  components: { ElButton },
};
</script>

在上面的代码中,通过 style 属性来自定义 ElButton 组件的背景色和字体大小。

综上所述,使用 Element Plus 可以快速规范并美化 Vue 页面,提高 Web 应用程序的用户体验和开发效率。

使用vue-router作为路由页面的跳转

Vue Router 是 Vue.js 官方提供的路由管理器,用于在 Vue 应用程序中实现客户端路由。以下是 Vue Router 的优点:

单页面应用:Vue Router 适用于单页面应用(SPA),可以使得应用程序的页面跳转更加流畅和快速,用户体验更佳。与传统多页面应用相比,单页面应用只需加载一次 HTML、CSS 和 JavaScript 文件,之后只需要通过 AJAX 加载数据并更新 DOM,能够提高页面的加载速度和性能。

强大的路由功能:Vue Router 提供了丰富的路由功能,包括嵌套路由、命名路由、动态路由、路由参数等,能够满足各种复杂的路由需求。例如,可以通过路由参数来传递数据,实现组件间的通信。

组件化开发:Vue Router 遵循组件化开发原则,将每个路由映射到一个组件中,实现了路由和组件的解耦,提高了代码可维护性和可读性。同时,组件化开发还能够使得组件的重用和独立测试变得更加容易。

插件机制:Vue Router 支持插件机制,可以通过插件来扩展或修改其功能,例如添加路由守卫、导航钩子等,提高了灵活性和可扩展性。例如,可以通过添加路由守卫来实现用户登录验证和权限控制。

动态加载:Vue Router 可以实现按需加载路由组件,能够减少应用程序的初始加载时间和页面大小,提高了性能。例如,在需要用到某个路由组件时,才进行加载和渲染。

易于学习和使用:Vue Router 遵循 Vue.js 的设计思想和语法风格,与 Vue.js 紧密集成,使得学习和使用门槛较低,上手快。同时,Vue Router 还提供了丰富的文档和示例,方便开发人员进行参考和学习。

综上所述,Vue Router 具有单页面应用、强大的路由功能、组件化开发、插件机制、动态加载、易学易用等优点,可以帮助前端开发人员快速构建复杂的应用程序,并且提高了开发效率和用户体验。

以下是一个简单的示例,演示如何在 Vue 中使用 Vue Router 实现页面的跳转。

安装 Vue Router

首先需要安装 Vue Router。可以通过 npm 命令来进行安装:

npm install vue-router

创建路由实例

在 Vue 应用程序中创建一个路由实例,并设置路由规则。例如,需要将 /home/about 路径分别映射到 HomeAbout 组件,可以通过以下方式创建路由实例:

import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './components/Home.vue';
import About from './components/About.vue';

Vue.use(VueRouter);

const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/about', component: About },
  ],
});

在上面的代码中,通过 Vue.use(VueRouter) 来安装 Vue Router 插件,并创建了一个名为 router 的路由实例。在 routes 属性中设置了两个路由规则,将 /home/about 路径分别映射到相应的组件。

配置路由

在 Vue 应用程序中配置路由,将路由实例注入到 Vue 实例中。例如:

import Vue from 'vue';
import App from './App.vue';
import router from './router';

new Vue({
  el: '#app',
  router,
  render: (h) => h(App),
});

在上面的代码中,将路由实例 router 注入到 Vue 实例中,并设置了根组件为 App 组件。

使用路由

在 Vue 应用程序中使用路由进行页面跳转。可以通过 <router-link> 组件来实现跳转链接,也可以通过编程式导航 this.$router.push() 来进行跳转。例如:

<template>
  <div>
    <h1>Vue Router Example</h1>
    <ul>
      <li><router-link to="/home">Home</router-link></li>
      <li><router-link to="/about">About</router-link></li>
    </ul>
    <router-view></router-view>
  </div>
</template>

在上面的代码中,使用 <router-link> 组件来生成跳转链接,并配合 <router-view> 组件来显示相应的组件内容。

综上所述,使用 Vue Router 作为路由页面的跳转具有简单易用、遵循官方规范、支持动态路由等优点,可以有效提高开发效率和用户体验。

使用vuex作为页面的状态管理

Vuex 是 Vue.js 官方提供的状态管理库,用于在大型 Vue 应用程序中管理组件之间共享的状态。以下是 Vuex 的优点:

集中式存储:Vuex 将应用程序的状态集中存储在一个容器中,可以方便地进行状态管理和控制,同时也能够更加清晰和准确地了解应用程序的数据流动。

状态管理规范:Vuex 提供了严格的状态管理规范,包括状态唯一性、状态改变只能通过提交 mutations 等,能够避免不必要的错误和数据混乱。

组件解耦:Vuex 能够将组件之间的状态解耦,使得组件的关注点更加单一化和专注化,同时也能够提高代码的复用性和可维护性。

插件机制:Vuex 支持插件机制,可以通过插件来扩展或修改其功能,例如添加状态订阅、调试工具等,提高了灵活性和可扩展性。

易于调试:Vuex 可以记录状态的变化和历史记录,支持时间旅行调试工具,能够方便地查找问题和排错。

以下是一个使用 Vuex 的简单示例:

安装 Vuex

首先需要安装 Vuex。可以通过 npm 命令来进行安装:

npm install vuex

创建 store 实例

在 Vue 应用程序中创建一个 Vuex store 实例,并定义状态、mutations 和 actions。例如,需要定义一个名为 counter 的状态和对应的 addsubtract mutations,可以通过以下方式创建 store 实例:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    counter: 0,
  },
  mutations: {
    add(state) {
      state.counter++;
    },
    subtract(state) {
      state.counter--;
    },
  },
  actions: {
    asyncAdd({ commit }) {
      setTimeout(() => {
        commit('add');
      }, 1000);
    },
  },
});

在上面的代码中,使用 Vue.use(Vuex) 来安装 Vuex 插件,并创建了一个名为 store 的 Vuex store 实例。在 state 属性中定义了一个名为 counter 的状态变量,初始值为 0。在 mutations 属性中定义了两个 mutations,分别是 addsubtract,用于增加和减少 counter 状态值。

在组件中使用

在 Vue 应用程序中通过 $store 属性来使用 Vuex store。例如,在某个组件中需要使用 counter 状态,可以通过以下方式来获取和修改它:

<script>
export default {
  name: 'Counter',
  computed: {
    counter() {
      return this.$store.state.counter;
    },
  },
  methods: {
    add() {
      this.$store.commit('add');
    },
    subtract() {
      this.$store.commit('subtract');
    },
    asyncAdd() {
      this.$store.dispatch('asyncAdd');
    },
  },
};
</script>

在上面的代码中,通过 computed 属性来获取 counter 状态值,并通过 methods 属性来提交 mutations 或执行 actions。

综上所述,Vuex 具有集中式存储、状态管理规范、组件解耦、插件机制、易于调试等优点,能够有效地管理大型 Vue 应用程序的状态和数据流动。

使用webpack作为打包软件

Webpack 是一个开源的 JavaScript 模块打包工具,能够将多个模块打包成一个文件。以下是 Webpack 的优点:

模块化:Webpack 支持模块化开发,可以将应用程序拆分成多个模块,使得代码可维护性和可读性变得更高。同时,也能够提高代码复用性和测试性。

自动化构建:Webpack 能够自动化地进行静态资源打包、编译、压缩等操作,提高了开发效率和部署速度。

插件机制:Webpack 支持插件机制,可以通过插件来扩展或修改其功能,例如添加代码压缩、图片优化等,提高了灵活性和可扩展性。

开发调试:Webpack 提供了强大的开发调试工具,例如热加载、source map 等,能够快速定位问题和修复错误。

生态系统:Webpack 有着庞大的生态系统,有许多社区贡献的插件和工具,能够满足各种不同的开发需求。

以下是一个使用 Webpack 的简单示例:

安装 Webpack

首先需要安装 Webpack。可以通过 npm 命令来进行安装:

npm install webpack webpack-cli --save-dev

创建配置文件

在应用程序根目录下创建 webpack.config.js 配置文件,定义入口、输出、加载器、插件等。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: ['file-loader'],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html',
    }),
  ],
};

在上面的代码中,定义了入口文件为 ./src/index.js,输出到 ./dist/bundle.js 文件中。使用了 Babel 和 CSS Loader 进行 JavaScript 和 CSS 文件的编译和转换,在图片资源中使用了 File Loader 进行处理。同时,还使用了 HtmlWebpackPlugin 插件来生成 HTML 文件。

执行打包命令

执行 Webpack 打包命令,将主文件和依赖打包成一个可运行的文件。

npm run build

综上所述,Webpack 具有模块化、自动化构建、插件机制、开发调试、生态系统等优点,是前端开发中不可或缺的工具之一,能够大大提高开发效率和代码质量。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值