HTML、CSS JavaScript axios vue基础语法 Element Ul
Vue基础
Vue安装与配置
基于脚手架创建前端工程,其所需要的环境如下:
node.js
前端项目的运行环境,其作用类似于Java
中的JDK
npm
JavaScript的包管理工具(npm
包含在node.js
中)Vue CLl
基于Vue
进行快速开发的完整系统,实现交互式的项目脚手架
在nodejs
的安装目录下创建node_cache
和node_global
两个文件夹
随后在cmd
中执行下面的命令,路径改为自己的
shell
npm config set prefix "D:\softwares\nodejs\node_global"
shell
npm config set cache "D:\softwares\nodejs\node_cache"
随后配置环境变量
全局安装最常用的 express
模块 进行测试,命令如下:
shell
npm install express -g
设置淘宝镜像:
shell
npm config set registry https://registry.npmmirror.com
利用npm
安装Vue CLI
,执行命令:
shell
npm i @vue/cli -g
随后使用 Vue CLl
创建前端工程:
方式一:vue create
项目名称
方式二:vue ui
我们主要是以第二种方式为主:
之后在浏览器上打开这个地址:
Vue项目创建
我们进行创建即可:
随后选择版本,我们选择最新的Vue3
最后点击创建即可,这个过程可能需要等一些时间,生成的文件如下:
前端项目启动后,服务端口默认为8080
,很容易和后端tomcat
端口号冲突如何修改前端服务的端口号?
在vue.config.js
文件中做如下配置:
js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer:{
port:7070
}
})
Vue
的组件以.vue
结尾,每个组件由三个部分组成:
Vue的基本用法
Vue的文本插值
作用:用来绑定 data 方法返回的对象属性
,用法:{``{}}
html
<template>
<div class="hello">
<h1>{{ name }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {name:"鹏翔"}
}
}
</script>
Vue的属性绑定
作用:为标签的属性绑定 data
方法中返回的属性,用法:v-bind:xxx
,简写为:xxx
,xxx即为属性名
html
<template>
<div class="hello">
<h1>{{ name }}</h1>
<div><input type="text" v-bind:value="name"></div>
<div><input type="text" :value="age"></div>
<div><img :src="img"></div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {
name:"鹏翔",age:18,img:"/assets/logo.png"
}
}
}
</script>
Vue的事件绑定
作用:为元素绑定对应的事件简写为 @xxx
,用法:v-on:xxx
,xxx
是事件,如click
html
<template>
<div class="hello">
<div><button @click="save()">保存</button></div>
<div><button v-on:click="save()">保存</button></div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {
name:"鹏翔",age:18,img:"/assets/logo.png"
}
},
methods:{
save(){
alert(this.name)
}
}
}
</script>
Vue的双向绑定
作用:表单输入项和 data
方法中的属性进行绑定,任意一方改变都会同步给另一方
用法:v-model
html
<template>
<div class="hello">
<h1>{{ age }}</h1>
<div><input type="text" v-bind:value="name"></div>
<div><input type="text" v-model="age"></div>
<div><button @click="save()">保存</button></div>
<div><button v-on:click="change()">改变</button></div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {
name:"鹏翔",age:18,img:"/assets/logo.png"
}
},
methods:{
save(){
alert(this.name)
},
change(){
this.age=19
}
}
}
</script>
Vue的条件渲染
作用:根据表达式的值来动态渲染页面元素用法:v-if、v-else、v-else-if
html
<div v-if="0<age<18">未成年</div>
<div v-else-if="18<age<150">成年</div>
<div v-else>妖怪</div>
Vue的Axios
Axios
是一个基于 promise
的 网络请求库,作用于浏览器和 node.js
中,发送ajax
异步请求
安装命令:
html
npm install axios
在VS-Code
的控制台下面安装,报错,这是没有权限导致的,博主尝试修改cache
和global
两个文件夹属性的,但依旧不行。
其实最简单的方法就是将VS-Code
关闭,然后以管理员身份运行就可以。
安装成功后,在package.joon
文件下会自动导入我们安装的版本
导入命令:
js
import axios from 'axios'
然而,我们在导入axios后却发生了报错:
'axios' is defined but never used"
这是由于这个变量axios
没有定义的缘故,只需要在package.json
中的eslintConfig
配置中的rules
中加上"no-unused-vars": "off"
,并重启服务即可。
ur:请求路径
data:请求体数据,最常见的是JSON格式数据
config:配置对象,可以设置查询参数、请求头信息
那么在做前后端分离项目时,我们的Vue项目是在7070的端口,而我们的后端项目在8080端口,这就涉及到请求跨域问题,如下面是通过axios发送post请求去登录:
js
send(){
axios.post("http://localhost:8080/admin/employee/login",
{username:"admin",password:"123456"},
).then(res =>{
console.log(res.data)
}).catch(error =>{
console.log(error.response)
})
}
此时前端F12调试台可以看到报错,Access-Control-Allow-Origin
即说明发生了跨域问题
html
Access to XMLHttpRequest at 'http://localhost:8080/admin/employee/login' from origin 'http://localhost:7070' 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.
该如何解决呢?可以通过代理来实现,即前端发送的请求先发给代理,随后代理再去转发。
POST方式请求
js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer:{
port:7070,
proxy:{
'/api':{//发送的请求中由api做标识,这个随便起
target:"http://localhost:8080",//转发的端口号
pathRewrite:{
"^/api":""//去掉请求中的api,其实可以认为是用api代替http://localhost:8080
}
}
}
}
})
此时的请求修改:
javascript
send(){
axios.post("/api/admin/employee/login",
{username:"admin",password:"123456"},
).then(res =>{
console.log(res.data)
}).catch(error =>{
console.log(error.response)
})
}
修改完后需要重启一下服务,随后运行,结果如下:
GET请求,此时报了401错误,这是由于JWT
令牌验证导致的
随后我们定义一个Token
,初始为空,先用Post
请求获取token
,后将该token作为配置传入Get
方法中。
javascript
<script>
import axios from 'axios'
var token=""
export default {
name: 'HelloWorld',
data(){
return {
name:"鹏翔",age:18,img:"/assets/logo.png"
}
},
methods:{
sendPost(){
axios.post("/api/admin/employee/login",
{username:"admin",password:"123456"},
).then(res =>{
this.token=res.data.data.token
console.log(res.data)
}).catch(error =>{
console.log(error.response)
})
},
sendGet(){
axios.get("/api/admin/workspace/businessData",
{headers:{
token:this.token
}}
).then(res =>{
console.log(this.token)
console.log(res.data)
})
}
}
}
</script>
统一请求方式,和AJAX
很像
javascript
sendCommon(){
axios({
url:"/api/admin/employee/login",
method:"post",
data:{username:"admin",password:"123456"},}
).then(res =>{
axios({
url:"/api/admin/workspace/businessData",
method:"get",
headers:{
token:res.data.data.token
}
}).then(res=>{
console.log(res.data)
})
}).catch(error =>{
console.log(error.response)
})
}}}
Vue-Router(路由配置)
vue 属于单页面应用,所谓的路由,就是根据浏览器路径
不同,用不同的视图组件
替换这个页面内容,即整个Vue中只有一个页面,切换不同路径就是调用不同组件来实现视觉上多个页面。
路由组成
路由组成:
VueRouter
:路由器,根据路由请求在路由视图中动态渲染对应的视图组件
<router-link>
:路由链接组件,浏览器会解析成
<router-view>
:路由视图组件,用来展示与路由路径匹配的视图组件
路由表:
标签式视图
路由链接组件与占位组件
当我们将<router-view>
删除后,他就找不到要渲染的位置:
编程式视图
那么要实现路由跳转,只能通过<router-link>
的方式吗,事实上,这种方式称为标签式,而我们接下来介绍一种使用编程式跳转视图的方法,即通过js
代码:
通过this.$router
获得路由对象,通过push
实现跳转
javascript
<script>
export default{
methods:{
jump(){
this.$router.push('/about')//这个路径不能瞎写,得是路由表里面配置的
}
}
}
</script>
点击按钮,即可实现跳转
重定向
404设置
那么该如何做呢?我们需要配置路由表
javascript
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
},
{
path: '/404',
component: () => import('../views/404View.vue')
},
{path:'/:pathMatch(.*)',redirect:'/404'}//表示上面的都匹配不上时执行这个,并重定向到404
]
嵌套路由
嵌套路由:组件内要切换内容,就需要用到嵌套路由(子路由)
实现步骤:
安装并导入 elementui
,实现页面布局(Container
布局容器)---ContainerView.vue
提供子视图组件,用于效果展示---P1View.vue、P2View.vue、P3View.vue
在 src/router/index.js
中配置路由映射规则(嵌套路由配置)
在布局容器视图中添加<router-view>
,实现子视图组件展示
在布局容器视图中添加<router-link>
,实现路由请求
接下来是具体实现:
安装并导入 elementui
,实现页面布局(Container
布局容器)---ContainerView.vue
Element-UI文档
博主按照要求使用下面的命令,却安装失败
shell
npm i element-ui -S
报错,这个错误似乎是由于npm版本过高导致的
javascript
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: skyrouter@0.1.0
npm ERR! Found: vue@3.4.23
npm ERR! node_modules/vue
npm ERR! vue@"^3.2.13" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer vue@"^2.5.17" from element-ui@2.15.14
npm ERR! node_modules/element-ui
npm ERR! element-ui@"*" from the root project
因此可以使用下面的命令来安装
shell
npm install --legacy-peer-deps element-ui --save
随后在main.js
中分别引入其js
与css
,同时使用Vue.use(ElementUI)
告诉Vue
要全局使用组件
javascript
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
注意:
在使用vue的时候,使用一个全局变量,ESLint的语法会出现ESLint: 'vue' is not defined.
(no-undef),说变量未定义,这时我们可以添加配置,取消这个校验。在.eslintrc.js文件中添加一个配置,位置如下图所示,我的全局变量就是vue
需要注意的是,Vue3
所使用的应该是Element-PLUS
,其不支持Element-ui
,因此需要使用:
javascript
npm install element-plus --save
导入并使用的写法:
javascript
import { createApp } from 'vue'
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(router),
app.use(ElementPlus),
app.mount('#app')
提供子视图组件,用于效果展示---userView.vue、orderView.vue、dishView.vue
在 src/router/index.js
中配置路由映射规则(嵌套路由配置)
javascript
{
path: '/main',
name: 'main',
component: () => import(/* webpackChunkName: "about" */ '../views/mainView.vue'),
//嵌套路由(子路由),对应的组件会展示在当前组件内部
redirect:"/main/user",
children:[
{
path: '/main/order',
component: () => import(/* webpackChunkName: "about" */ '../views/orderView.vue')
},
{
path: '/main/user',
component: () => import(/* webpackChunkName: "about" */ '../views/userView.vue')
},
{
path: '/main/dish',
component: () => import(/* webpackChunkName: "about" */ '../views/dishView.vue')
},
]
},
在布局容器视图中添加<router-view>
,实现子视图组件展示
在布局容器视图中添加<router-link>
,实现路由请求
html
<template>
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">
<router-link to="/user">用户管理</router-link> <br>
<router-link to="/dish">菜品管理</router-link> <br>
<router-link to="/order">订单管理</router-link> <br>
</el-aside>
<el-main><router-view/></el-main>
</el-container>
</el-container>
</template>
最终的实现效果
VueX状态管理
vuex
是一个专为Vue.js
应用程序开发的状态管理库vuex
可以在多个组件之间共享数据,并且共享的数据是响应式的,即数据的变更能及时渲染到模板vuex
采用集中式存储管理所有组件的状态
shell
npm install vuex@next --save
核心概念
state:状态对象,集中定义各个组件共享的数据
mutations:类似于一个事件,用于修改共享数据,要求必须是同步函数
actions:类似于mutation,可以包含异步操作,通过调用mutation来改变共享数据
要想使用VueX功能,就需要创建具有VueX功能的脚手架。
创建完成后,我们发现多了一个store
文件夹
那么如何使用 vuex?
state管理共享数据
在 store
对象的 state
属性中定义共享数据
javascript
state: {
name:"游客"
},
全局调用:
javascript
<h1>{{ $store.state.name }}</h1>
mutations 修改数据
在 store
对象的 mutations
属性中定义修改共享数据的函数(这个函数只能是同步的)
javascript
//修改数据必须通过mutations
mutations: {
setName(state,name){
state.name=name
}
}
随后调用时只能通过store
对象的commit
方法调用:
javascript
update(){
this.$store.commit("setName","李四")//通过commit方法指定要执行的方法名和传入的参数
},
actions 异步修改数据
在 store
对象的 actions
属性中定义调用 mutation
的函数,可以进行异步操作mutations
中的函数
javascript
actions: {
sendAJAX(context){
axios({
url:"api/admin/employee/login",
data:{
username:"admin",
password:"123456"
},
method:"post"
}).then(res=>{
if(res.data.code==1){
context.commit("setName",res.data.data.name)
}
})
}
},
actions 中定义的函数不能直接调用,只能通过 store 对象的 dispatch方法调用:
javascript
updateByAction(){
this.$store.dispatch("sendAJAX")//通过dispatch方法指定要执行的action中方法
}
TypeScript
TypeScript介绍
- TypeScript(简称:TS)是微软推出的开源语言
- TypeScript 是JavaScript 的超集(JS 有的 TS 都有)
- TypeScript = Type +JavaScript(在JS 基础上增加了
类型
支持) - TypeScript 文件扩展名为 ts
- TypeScript 可编译成标准的 JavaScript,并且在编译时进行类型检查
TS 为什么要增加类型支持 ?
- TS 属于静态类型编程语言,JS 属于动态类型编程语言
- 静态类型在编译期做类型检查,动态类型在执行期做类型检查
- 对于 JS 来说,需要等到代码执行的时候才能发现错误(晚)
- 对于 TS 来说,在代码编译的时候就可以发现错误(早)
- 配合 VSCode 开发工具,TS 可以提前到在编写代码的同时就发现代码中的错误,减少找 Bug、改 Bug 的时间
如何理解 TypeScript ?
- 是 JavaScript 的超集,兼容 JavaScript扩展了 JavaScript 的语法,文件扩展名为 ts可以编译成标准的
JavaScript,并且可以在编译时进行类型检查 - 全局安装
npminstall- g typescript
- 使用 tsc 命令将 ts 文件编译成 js 文件
TypeScript项目创建
重新手动配置一下,可以看到只是开发依赖中有TypeScript
,这是由于我们在最终运行时都是编译为JS
代码的,即运行时是不需要TypeScript
依赖的
可以看到加入了TypeScript的代码以ts
结尾
TypeScript入门案例
VS-Code
下的命令窗口执行tsc
命令报下面的错误
javascript
tsc : 无法加载文件 D:\softwares\nodejs\node_global\tsc.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=
135170 中的 about_Execution_Policies。
所在位置 行:1 字符: 1
+ tsc .\test1.ts
+ ~~~
+ CategoryInfo : SecurityError: (:) [],PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
解决方法,win+x打开管理员shell,然后执行命令set-ExecutionPolicy RemoteSigned
,随后再在VS-Code
的控制台运行就不报错了
编写的ts代码
javascript
let username:string="李白"
let age:number=18
let isTrue:boolean=true
console.log(username)
console.log(age)
console.log(isTrue)
编译后的js代码
javascript
var username = "李白";
var age = 18;
var isTrue = true;
console.log(username);
console.log(age);
console.log(isTrue);
字面量类型
指定参数只能取哪些值,作用类似于java中的枚举
因为我们设定参数只能接收字符类型的left或right,所以其他的会报错
利用node
运行js
,node
相当于Java
中的JDK
接口类型
javascript
//定义接口
interface Cat{
name:string,
age:number
}
//定义变量类型为Cat
const cat1:Cat={name:"小花",age:2}
编译后的js文件中是没有interface的,被擦除了
小技巧:
如果我们向要让接口中的参数有时需要传入,有时不需要传入呢,我们可以在变量后加一个?
即可
Class类
javascript
class User{
username:string;
constructor(name:string){
this.username=name
}
study(){
console.log(this.username)
}
}
let user:User=new User("鹏翔")//const代表必须在生成时就给定值,不能修改,let则可以修改
user.study()
编译后的js
,将原本的类变为了方法,同时,无论是声明常量类型const
还是变量类型let
,编译为js
后都是var
javascript
var User = /** @class */ (function () {
function User(name) {
this.username = name;
}
User.prototype.study = function () {
console.log(this.username);
};
return User;
}());
var user = new User("鹏翔");
user.study();
实现接口:
javascript
interface Animal{
name:string
eat():void
}
class Bird implements Animal{
name:string
constructor(name:string){
this.name=name
}
eat(){
console.log(this.name+"在吃东西")
}
}
const bird=new Bird("燕子")
bird.eat()
class的继承
javascript
interface Animal{
name:string
eat():void
}
class Bird implements Animal{
name:string
constructor(name:string){
this.name=name
}
eat(){
console.log(this.name+"在吃东西")
}
}
const bird=new Bird("燕子")
bird.eat()
class Parrot extends Bird{
say(name:string):void{
console.log(name+"说你好")
}
}
const parrot=new Parrot("鹦鹉")
parrot.say("鹦鹉")