动手实践!从零开始实现Springboot+Vue登录(附源码)

作者:Eli Shaw

blog.csdn.net/xiaojinlai123/article/details/90694372

一、简述

最近学习使用Vue实现前端后端分离,在Github上有一个很好的开源项目:mall,正所谓百看不如一练,自己动手实现了一个Springboot+Vue的登录操作,在此记录一下踩过的坑。

文章最后补充两端的GitHub代码,之所以放在最后,是因为文章写的很细致了,动手操作一下会更有帮忙,如果有很大出入可以比对原码,找找问题。

二、开发工具

VSCode

IDEA

Vue 的安装就不说了,有很多文章,但是Springboot+Vue整合的完整文章相对较少,所以我主要记录一下这两端整合时的内容。

(Vue安装后就会有 npm 或 cnpm,相应的介绍也不说了,Vue官网可查看)

Vue 开发

一、打开 cmd 创建 Vue 项目,并添加 Vue 依赖的框架:

1.创建 Vue 项目(进入自己想创建的文件夹位置,我放在 D:\VSCodeWorkSpace),创建语句 vue create vue-spring-login-summed,方向键选择创建方式,我选择的默认

2.进入到创建的 Vue 项目目录,添加依赖框架:

cd vue-spring-login-summed (进入到项目根目录)
vue add element (添加 element,一个 element 风格的 UI 框架)
npm install axios (安装 axios,用于网络请求)
npm install vuex --save(安装 Vuex,用于管理状态)
npm install vue-router (安装 路由,用于实现两个 Vue 页面的跳转)

以上命令截图如下:

1)添加 Element

2)添加 axios

3)添加 Vuex

4)添加 路由

到此相关依赖的架包添加完毕,输入 code . 打开 VSCode

二、添加目录结构

在 VSCode 下看到 Vue 整体项目结构如下

现在需要创建相应功能的目录结构,进行分层开发,需要在 src 目录下创建下面几个目录

  • api (网络请求接口包)

  • router (路由配置包)

  • store (Vuex 状态管理包)

  • utils (工具包)

  • views (vue 视图包,存放所有 vue 代码,可根据功能模块进行相应分包)

创建后的目录结构如下

三、运行项目

现在可以运行项目了,在 VSCode 菜单栏依次选择:终端 —— 运行任务...

这里使用的是 serve 模式,即开发模式运行的项目

在浏览器输入:http://localhost:8080/

这是 Vue 默认的页面,代表项目创建成功了,在进行代码开发前,先贴上项目整体结构,防止不知道在哪创建

四、View 层代码编写

编写三个 vue 文件:login.vue(登录页面)、success.vue(登录成功页面)、error.vue(登录失败页面)

1.login.vue

代码如下(比较懒,直接从 mall 扒下来的代码,去掉了一些功能)

<template>
  <div>
    <el-card class="login-form-layout">
      <el-form
        autocomplete="on"
        :model="loginForm"
        ref="loginForm"
        label-position="left"
      >
        <div style="text-align: center">
          <svg-icon icon-class="login-mall" style="width: 56px;height: 56px;color: #409EFF"></svg-icon>
        </div>
        <h2 class="login-title color-main">mall-admin-web</h2>
        <el-form-item prop="username">
          <el-input
            name="username"
            type="text"
            v-model="loginForm.username"
            autocomplete="on"
            placeholder="请输入用户名"
          >
            <span slot="prefix">
              <svg-icon icon-class="user" class="color-main"></svg-icon>
            </span>
          </el-input>
        </el-form-item>
        <el-form-item prop="password">
          <el-input
            name="password"
            :type="pwdType"
            @keyup.enter.native="handleLogin"
            v-model="loginForm.password"
            autocomplete="on"
            placeholder="请输入密码"
          >
            <span slot="prefix">
              <svg-icon icon-class="password" class="color-main"></svg-icon>
            </span>
            <span slot="suffix" @click="showPwd">
              <svg-icon icon-class="eye" class="color-main"></svg-icon>
            </span>
          </el-input>
        </el-form-item>
        <el-form-item style="margin-bottom: 60px">
          <el-button
            style="width: 100%"
            type="primary"
            :loading="loading"
            @click.native.prevent="handleLogin"
          >登录</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>
 
<script>
export default {
  name: "login",
  data() {
    return {
      loginForm: {
        username: "admin",
        password: "123456"
      },
      loading: false,
      pwdType: "password",
    };
  },
  methods: {
    showPwd() {
      if (this.pwdType === "password") {
        this.pwdType = "";
      } else {
        this.pwdType = "password";
      }
    },
    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true;
          this.$store
            .dispatch("Login", this.loginForm)
            .then(response => {
              this.loading = false;
              let code = response.data.code;
              if (code == 200) {
                this.$router.push({
                  path: "/success",
                  query: { data: response.data.data }
                });
              } else {
                this.$router.push({
                  path: "/error",
                  query: { message: response.data.message }
                });
              }
            })
            .catch(() => {
              this.loading = false;
            });
        } else {
          // eslint-disable-next-line no-console
          console.log("参数验证不合法!");
          return false;
        }
      });
    }
  }
};
</script>
 
<style scoped>
.login-form-layout {
  position: absolute;
  left: 0;
  right: 0;
  width: 360px;
  margin: 140px auto;
  border-top: 10px solid #409eff;
}
 
.login-title {
  text-align: center;
}
 
.login-center-layout {
  background: #409eff;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  margin-top: 200px;
}
</style>

2.success.vue

<template>
  <div>
    <h1>Welcome!{{msg}}</h1>
  </div>
</template>
<script>
export default {
  data() {
    return {
      msg: this.$route.query.data
    };
  },
//   data() { //这种方式也可以
//     return {
//       msg: null
//     };
//   },
  // created() {
  //   this.msg = this.$route.query.data;
  // }
}
</script>

3.error.vue

<template>
  <div>
    <h1>登录错误:{{msg}}</h1>
  </div>
</template>
<script>
export default {
  // data() {
  //   return {
  //     msg: this.$route.query.data
  //   };
  // }, //使用这种方式也可以显示 msg
  data() {
    return {
      msg: null
    };
  },
  created() {
    this.msg = this.$route.query.message;
  }
};
</script>

五、路由

页面写好了,我们需要依次显示这三个页面,这里我们统一使用路由来管理显示页面,路由的官方文档见:

https://router.vuejs.org/zh/

本着先实践,后理解的码农学习方式。我们先使用路由显示三个页面后,再去理解Vue路由这个功能点。

1.创建路由配置文件

在刚才建立的 router 文件夹下创建一个 index.js 文件,内容如下

import Vue from 'vue' //引入 Vue
import VueRouter from 'vue-router' //引入 Vue 路由
 
Vue.use(VueRouter); //安装插件
 
export const constantRouterMap = [
    //配置默认的路径,默认显示登录页
    { path: '/', component: () => import('@/views/login')},
 
    //配置登录成功页面,使用时需要使用 path 路径来实现跳转
    { path: '/success', component: () => import('@/views/success')},
 
    //配置登录失败页面,使用时需要使用 path 路径来实现跳转
    { path: '/error', component: () => import('@/views/error'), hidden: true }
]
 
export default new VueRouter({
    // mode: 'history', //后端支持可开
    scrollBehavior: () => ({ y: 0 }),
    routes: constantRouterMap //指定路由列表
})

2.将路由添加到程序入口

路由配置文件写好,我们需要把他引入到 main.js 中,在项目的 src 目录根节点下,找到 main.js,添加内容如下:

import Vue from 'vue'
import App from './App.vue'
import './plugins/element.js'
import router from './router' //引入路由配置
 
Vue.config.productionTip = false
 
new Vue({
  render: h => h(App),
  router, //使用路由配置
}).$mount('#app')

3.配置路由的出入口

现在路由已经完全引入到项目了,但是路由还需要一个出入口,这个出入口用来告诉路由将路由的内容显示在这里。上面 main.js 配置的第一个 vue 显示页面为 App.vue ,因此我们修改 App.vue 内容如下

<template>
  <div id="app">
    <!-- 路由的出入口,路由的内容将被显示在这里 -->
    <router-view/>
  </div>
</template>
 
<script>
  export default {
    name: 'App'
  }
</script>

 就是显示路由的出入口。

现在保存 App.vue 文件后,当前项目会被重新装载运行,在刚才浏览的界面就会看到登录界面如下:

4.路由跳转

在 login.vue 中可以使用 this.$router.push({path: "路径"}) 来跳转到指定路径的路由组件中,下面是通过路由跳转到 error.vue 与 success.vue的代码

this.$router.push({path: "/success"}); //跳转到成功页
或
this.$router.push({path: "/error"}); //跳转到失败页

六、使用 Vuex + Axios 方式进行网络请求

1.Axios

axios 是一个网络请求构架,官方推荐使用这种方式进行 http 的请求。

1) 在 utils 包下封装一个请求工具类 request.js

import axios from 'axios' //引入 axios
import baseUrl from '../api/baseUrl' //使用环境变量 + 模式的方式定义基础URL
 
// 创建 axios 实例
const service = axios.create({
  baseURL: baseUrl, // api 的 base_url
  timeout: 15000, // 请求超时时间
})
 
export default service

这里的 baseUrl 涉及 Vue CLI3 的环境变量与模式的概念,见:Vue 环境变量和模式(设置通用baseUrl)

2) 登录请求接口 API

在 api 文件夹下,创建一个登录API文件:login.js

import request from '@/utils/request' //引入封装好的 axios 请求
 
export function login(username, password) { //登录接口
  return request({ //使用封装好的 axios 进行网络请求
    url: '/admin/login',
    method: 'post',
    data: { //提交的数据
      username,
      password
    }
  })
}

2.使用 Vuex 封装 axios

Vuex 是一个状态管理构架,官方文档:https://vuex.vuejs.org/zh/

1)封装 Vuex 中的 module

在 store 文件夹下创建一个 modules 文件夹,然后在此文件夹下创建一个 user.js 文件

import { login } from '@/api/login'//引入登录 api 接口
 
const user = {
  actions: {
    // 登录
    Login({ commit }, userInfo) { //定义 Login 方法,在组件中使用 this.$store.dispatch("Login") 调用
      const username = userInfo.username.trim()
      return new Promise((resolve, reject) => { //封装一个 Promise
        login(username, userInfo.password).then(response => { //使用 login 接口进行网络请求
          commit('') //提交一个 mutation,通知状态改变
          resolve(response) //将结果封装进 Promise
        }).catch(error => {
          reject(error)
        })
      })
    },
  }
}
export default user

这里的代码值得解释一下:官方文档对应:

https://vuex.vuejs.org/zh/guide/actions.html

1.首先引入 login 接口,之后使用登录接口进行网络请求。

2.定义一个 名为 Login 的 action 方法,Vue 组件通过 this.$store.dispatch("Login") 调用

3.Promise,这个类很有意思,官方的解释是“store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise”。这话的意思组件中的 dispatch 返回的仍是一个 Promise 类,因此推测 Promise 中的两个方法 resolve() 与 reject() 分别对应 dispatch 中的 then 与 catch。

2)创建 Vuex

在 store 文件夹下创建一个 index.js 文件

import Vue from 'vue' //引入 Vue
import Vuex from 'vuex' //引入 Vuex
import user from './modules/user' //引入 user module
 
Vue.use(Vuex)
 
const store = new Vuex.Store({
  modules: {
    user //使用 user.js 中的 action
  }
})
 
export default store

3) 将 Vuex 添加到 main.js 文件

修改之前的 main.js 文件如下:

import Vue from 'vue'
import App from './App.vue'
import './plugins/element.js'
import router from './router' //引入路由配置
import store from './store' //引入 Vuex 状态管理
 
Vue.config.productionTip = false
 
new Vue({
  render: h => h(App),
  router, //使用路由配置
  store //使用 Vuex 进行状态管理
}).$mount('#app')

重新运行项目,在 Chrome 浏览器中进入调试模式,点击登录按钮

可以看到有发送一个 8088 端口的请求,至此 Vue 端的所有代码已经完成。

Springboot 开发

项目创建就不提了,网上有很多,只要使用 Spring Assistant 创建就好。

整体目录结构如下

1.在 application.yml 修改端口号

不要和 Vue 在一个 8080 端口上:

server:port: 8088

2.解决跨域问题

这里有一个跨域问题,即 Vue 使用 8080 端口,要访问 8088 端口的服务器,会报错。错误信息如下:

Access to XMLHttpRequest at 'http://localhost:8088/admin/login' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这个问题在 Vue 端或在 Springboot 端处理都可以,我在 Springboot 端处理的,写一个 CorsConfig 类内容如下,不要忘了 @Configuration 注解。

@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1
        corsConfiguration.addAllowedHeader("*"); // 2
        corsConfiguration.addAllowedMethod("*"); // 3
        return corsConfiguration;
    }
 
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4
        return new CorsFilter(source);
    }
}

3.IErrorCode 接口

Java 版本

public interface IErrorCode {
    long getCode();
    String getMessage();
}

Kotlin 版本

interface IErrorCode {
    fun getCode(): Long
    fun getMessage(): String
}

4.CommonResult 类

Java 版本

public class CommonResult<T> {
    private long code;
    private String message;
    private T data;
 
    protected CommonResult() {
    }
 
    protected CommonResult(long code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }
 
    /**
     * 成功返回结果
     *
     * @param data 获取的数据
     */
    public static <T> CommonResult<T> success(T data) {
        return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
    }
 
    /**
     * 成功返回结果
     *
     * @param data    获取的数据
     * @param message 提示信息
     */
    public static <T> CommonResult<T> success(T data, String message) {
        return new CommonResult<T>(ResultCode.SUCCESS.getCode(), message, data);
    }
 
    /**
     * 失败返回结果
     *
     * @param errorCode 错误码
     */
    public static <T> CommonResult<T> failed(IErrorCode errorCode) {
        return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);
    }
 
    /**
     * 失败返回结果
     *
     * @param message 提示信息
     */
    public static <T> CommonResult<T> failed(String message) {
        return new CommonResult<T>(ResultCode.FAILED.getCode(), message, null);
    }
 
    /**
     * 失败返回结果
     */
    public static <T> CommonResult<T> failed() {
        return failed(ResultCode.FAILED);
    }
 
    /**
     * 参数验证失败返回结果
     */
    public static <T> CommonResult<T> validateFailed() {
        return failed(ResultCode.VALIDATE_FAILED);
    }
 
    /**
     * 参数验证失败返回结果
     *
     * @param message 提示信息
     */
    public static <T> CommonResult<T> validateFailed(String message) {
        return new CommonResult<T>(ResultCode.VALIDATE_FAILED.getCode(), message, null);
    }
 
    /**
     * 未登录返回结果
     */
    public static <T> CommonResult<T> unauthorized(T data) {
        return new CommonResult<T>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);
    }
 
    /**
     * 未授权返回结果
     */
    public static <T> CommonResult<T> forbidden(T data) {
        return new CommonResult<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
    }
 
    public long getCode() {
        return code;
    }
 
    public void setCode(long code) {
        this.code = code;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
 
    public T getData() {
        return data;
    }
 
    public void setData(T data) {
        this.data = data;
    }
}

Kotlin 版本

class CommonResult<T> {
    var code: Long = 0
    var message: String? = null
    var data: T? = null
 
    constructor(code: Long, message: String, data: T?) {
        this.code = code
        this.message = message
        this.data = data
    }
 
    companion object {
 
        /**
         * 成功返回结果
         * @param data 获取的数据
         */
        fun <T> success(data: T): CommonResult<T> {
            return CommonResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data)
        }
 
        /**
         * 成功返回结果
         * @param data 获取的数据
         * @param  message 提示信息
         */
        fun <T> success(data: T, message: String): CommonResult<T> {
            return CommonResult(ResultCode.SUCCESS.getCode(), message, data)
        }
 
        /**
         * 失败返回结果
         * @param errorCode 错误码
         */
        fun <T> failed(errorCode: IErrorCode): CommonResult<T> {
            return CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null)
        }
 
        /**
         * 失败返回结果
         * @param message 提示信息
         */
        fun <T> failed(message: String): CommonResult<T> {
            return CommonResult<T>(ResultCode.FAILED.getCode(), message, null)
        }
 
        /**
         * 失败返回结果
         */
        fun failed(): CommonResult<Any> {
            return failed(ResultCode.FAILED)
        }
 
        /**
         * 参数验证失败返回结果
         */
        fun validateFailed(): CommonResult<Any> {
            return failed(ResultCode.VALIDATE_FAILED)
        }
 
        /**
         * 参数验证失败返回结果
         * @param message 提示信息
         */
        fun <T> validateFailed(message: String): CommonResult<T> {
            return CommonResult<T>(ResultCode.VALIDATE_FAILED.getCode(), message, null)
        }
 
        /**
         * 未登录返回结果
         */
        fun <T> unauthorized(data: T): CommonResult<T> {
            return CommonResult(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data)
        }
 
        /**
         * 未授权返回结果
         */
        fun <T> forbidden(data: T): CommonResult<T> {
            return CommonResult(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data)
        }
    }
}

5.ResultCode 枚举

Java 版本

public enum ResultCode implements IErrorCode {
    SUCCESS(200, "操作成功"),
    FAILED(500, "操作失败"),
    VALIDATE_FAILED(404, "参数检验失败"),
    UNAUTHORIZED(401, "暂未登录或token已经过期"),
    FORBIDDEN(403, "没有相关权限");
    private long code;
    private String message;
 
    private ResultCode(long code, String message) {
        this.code = code;
        this.message = message;
    }
 
    public long getCode() {
        return code;
    }
 
    public String getMessage() {
        return message;
    }
}

Kotlin 版本

enum class ResultCode(private val code: Long, private val message: String) : IErrorCode {
    SUCCESS(200, "操作成功"),
    FAILED(500, "操作失败"),
    VALIDATE_FAILED(404, "参数检验失败"),
    UNAUTHORIZED(401, "暂未登录或token已经过期"),
    FORBIDDEN(403, "没有相关权限");
 
    override fun getCode(): Long {
        return code
    }
 
    override fun getMessage(): String {
        return message
    }
}

6.User类

Java 版本

public class User {
 
    private int id;
    private String username;
    private String password;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
}

Kotlin 版本

data class User(
        val id: Int,
        val username: String,
        val password: String)

7.LoginController 类

Java 版本

@RestController
public class LoginController {
 
    @RequestMapping(value = "/admin/login", method = RequestMethod.POST)
    public CommonResult login(@RequestBody User user) {
        if (user.getUsername().equals("admin") && user.getPassword().equals("123456"))
            return CommonResult.success("admin");
        else
            return CommonResult.validateFailed();
    }
}

Kotlin 版本

@RestController //此注解是 @ResponseBody 和 @Controller 的组合注解,可返回一个 JSON
class LoginController {
 
    @RequestMapping(value = ["/admin/login"], method = [RequestMethod.POST])
    fun admin(@RequestBody user: User): CommonResult<*> {
        return if (user.username == "admin" && user.password == "123456") {
            CommonResult.success("admin")
        } else {
            CommonResult.validateFailed()
        }
    }
}

启动两端程序

输入正确的账号密码

输入错误的账号密码

七、GitHub源码地址

vue端:https://github.com/xiaojinlai/vue-spring-login-summed

Java端:https://github.com/xiaojinlai/vue-login-java

Java端 - Kotlin版本:https://github.com/xiaojinlai/vue-login-kotlin

注:Kotlin 版本只是我本人用习惯了 Kotlin,就功能而言与Java是一样的。大家如果不喜欢可以不用理会,如果有感兴趣的可以看看,Kotlin 是 Google 推出的一种简洁性语言,主推在 Android 上,用习惯后还是蛮喜欢的。学习起来也不难,内容也不多,推荐一个学习 Kotlin 的网址:https://www.kotlincn.net/docs/reference/

END

推荐好文

强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

为什么MySQL不推荐使用uuid或者雪花id作为主键?

为什么建议大家使用 Linux 开发?爽(外加七个感叹号)

IntelliJ IDEA 15款 神级超级牛逼插件推荐(自用,真的超级牛逼)

炫酷,SpringBoot+Echarts实现用户访问地图可视化(附源码)

记一次由Redis分布式锁造成的重大事故,避免以后踩坑!

十分钟学会使用 Elasticsearch 优雅搭建自己的搜索系统(附源码)


  • 1
    点赞
  • 1
    评论
  • 8
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

<div> 适用人群 <p> Java开发人员,Vue开发人员,前后端分离开发人员,权限管理和配置开发人员 </p> </div> <div> 课程概述 <div style="color:#666666;"> 【讲师介绍】<br /> 讲师职称:<br />               现某知名大型互联网公司资深架构师,技术总监,职业规划师,首席面试官,曾在某上市培训机构,高校任教多年。<br />             Array(Array老师)10多年互联网公司实战经验,知名的大型互联网公司的架构师,高管等职,在企业长期从事于技术的源码阅读和新技术的研究;擅长于职业规划,面试辅导,从事面试官多年;擅长于JAVA,人工智能AI应用,Xmind等等,曾服役于国内某上市培训机构数年,独特的培训思路,培训体系,培训方式,实践的职场技能,职场现状,职场晋升等让你快速适应企业职场的所需。 <br /> 【课程介绍】<br /> 技术选型<br /> 开发环境:Eclipse/Idea ,JDK 1.8以上 <br /> 后端技术<br /> 核心框架:SpringBoot2.x框架系列(同样适用Springcloud F版本以后的版本),如下(节选):    <br /> 持久层框架:MyBatis 3.x + Mybatis-plus 3.x<br /> 日志管理:SLF4J 1.7 + Log4j2 2.7<br /> 工具类:Apache Commons、Jackson 、fastjson、Gson<br /> 权限验证<br /> 前端技术  <br /> Vue  <br /> Vue-cli<br /> ElementUI ---https://element.eleme.io/<br /> JSX (JavaScript Xml)<br /> 前台的权限验证和路由设置<br /> 开发模式  <br />      前后端分离的开发<br /> 数据库 <br />       Mysql5<br /> IDE<br />     Intellij Idea </div> </div>
相关推荐
<p> <span style="font-size:24px;"><img src="https://img-bss.csdn.net/202002111502403886.png" alt="" /><br /> </span> </p> <p> <span style="font-size:24px;"><img src="https://img-bss.csdn.net/202002111502521739.jpg" alt="" /><br /> </span> </p> <p> <span style="font-size:24px;">本课程是Vue的快速入门课程,涉及到的课程知识点:Vue环境的快速搭建, 会使用Vue的生命周期的钩子函数; 会使用vue常见指令;会使用vue计算属性和watch监控;会编写Vue组件;掌握组件间通信,会创建Vue实例,知道Vue的常见属性</span> </p> <br /> <br /> <span style="font-size:24px;">大家都知道涛哥最关心的是找工作,这段时间出去面试的时候会经常会被问及到Vue相关的知识,所以涛哥迫不及待的赶紧出了一版Vue相关的教程,有人问:我们做后台会前台干什么呀?是因为现在的公司老板都想招复合型的人才,招一个Java开发回来恨不得前后台都会,所以我们Java开发人员也要掌握一些前端相关的技能。Java这边现在前端用的比较多的就是VUE,所以大家还是要赶紧学习起来,为了你不被淘汰,为了你能快速适应公司的发展速度,快速找到一份满意的工作,赶紧学起来吧。本课程是Vue的快速入门课程,涉及到的课程知识点:Vue环境的快速搭建,?会使用Vue的生命周期的钩子函数;?会使用vue常见指令;会使用vue计算属性和watch监控;会编写Vue组件;掌握组件间通信;</span><br /> <br /> <span style="font-size:24px;">用2小时看完,就可以快速上手公司里的项目,后期还会有实战项目上线,请大家持续关注。</span><br /> <br /> <span style="font-size:24px;"></span>
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页