1. 使用脚手架创建项目
1.1 准备工作
- win+R,在弹出的数据框中输入cmd,数据命令查看node以及npm版本
- 下载vue cli
1.2 创建项目
1.2.1 创建一个英文目录文件夹,cmd打开命令命令提示符
1.2.2 vue ui命令打开控制台
1.2.3 创建项目
创建成功
1.3 项目结构
1.4 将项目在VSCode打开,终端运行页面
使用命令npm run serve命令打开
1.5 修改服务端口号
在vue.config.js中修改服务端口号,防止与后端tomcat端口冲突
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,devServer:{port: 7070}
})
保存文件,重启项目端口号修改完毕
2. vue基础回顾
2.1 文本插值
<template><div class="hello">{{ name }}</div>
</template><script>
export default {data() {return {name: 'I LOVE YOU'}}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
2.2 属性绑定
为标签的属性绑定data方法中返回的属性
<template><div class="hello">{{ name }}<input type="name" :value="age"></div>
</template><script>
export default {data() {return {name: 'I LOVE YOU',age: 18}}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
2.3 事件绑定
<template><div class="hello">{{ name }}<input type="name" :value="age"><!-- 点击事件 --><button @click="dianji()">点击</button></div>
</template><script>
export default {data() {return {name: 'I LOVE YOU',age: 18}},methods: {dianji() {alert('点击了')}}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
2.4 双向绑定
通过v-model将数据区的数据与输入框数据双向绑定
<template><div class="hello">{{ name }}<input type="name" :value="age"><!-- 点击事件 --><button @click="dianji()">点击</button><input type="text" v-model="name"></div>
</template><script>
export default {data() {return {name: 'I LOVE YOU',age: 18}},methods: {dianji() {alert('点击了')}}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
2.5 条件渲染
<template><div class="hello"><div v-if="sex==1">男</div><div v-else-if="sex==2">女</div><div v-else>未知</div></div>
</template><script>
export default {data() {return {sex:2}},methods: {}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
2.6 axios
Axios是一个基于promise的网络请求库,作用于浏览器和node.js中,用于发ajax异步请求,实现前后端交互
2.6.1 下载axios
npm install axios
2.6.2 在项目中使用axios
2.6.3 axios的API
- url:请求路径
- data:请求体数据,最常见的是JSON格式
- config:配置对象,可以设置查询参数,请求头信息
2.6.4 axios请求的跨域问题
正常情况下,前端数据一个服务,后端属于一个服务,在不同的域里,所以会出现跨域问题,解决方法就是在vue.config.js文件中配置代理:
<template><button @click="request11()"></button></div>
</template><script>
// 导入axios
import axios from 'axios'export default {data() {return {sex:2}},methods: {request11(){axios.post('http://localhost:8080/user/login',{username:'admin', // json数据password:'123456'}).then(res=>{ // 成功回调console.log(res.data)}).catch(err=>{ // 错误回调console.log(err)})}}
}
</script>
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,devServer:{port: 7070,proxy:{// 配置请求代理,用于将特定请求转发到后端服务器,解决跨域问题'/api':{// 将请求转发到的目标服务器地址target:'http://localhost:8080',changeOrigin:true, // 是否更改请求的来源,通常用于处理虚拟主机的情况pathRewrite:{'^/api':'' // 移除请求路径中的 '/api' 前缀,以便目标服务器正确处理请求}}}}
})
2.6.5 发送请求
- 方式一
<template><div class="hello"><div v-if="sex==1">男</div><div v-else-if="sex==2">女</div><div v-else>未知</div><button @click="request11()">按钮</button></div>
</template><script>
// 导入axios
import axios from 'axios'export default {data() {return {sex:2}},methods: {request11(){ axios.post('http://localhost:8080/user/login',{username:'admin', // json数据password:'123456'}).then(res=>{ // 成功回调console.log(res.data)}).catch(err=>{ // 错误回调console.log(err)})},req(){axios.get('http://localhost:8080/user/getUserById',{// 携带请求头headers:{token:'xxxxxxxxxxxxxxxxxxxxxxxxxx'}}).then(res=>{console.log(res.data)}).catch(err=>{console.log(err)})}}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
- 方式二
<button @click="handleSend()"></button>handleSend(){axios({url:'http://localhost:8080/user/login',method:'post',data:{username:'admin',password:'<PASSWORD>'}}).then(res=>{console.log(res.data)axios({url:'http://localhost:8080/user/info',method:'get',headers:{token:res.data.data.token}})}).catch(err=>{console.log(err)})}
3. 路由Vue-Router
vue属于单页面应用,路由的作用就是根据浏览器路径不同,用不同的视图组件替换掉这个页面内容。实现不同的路径,对应不同的页面展示
3.1 创建带有路由的项目
创建好之后,package.json中有vue-router的依赖
main.js中引入了router,说明这个项目具备了路由功能
3.2 路由配置
路由组成:
- VueRouter:路由器,根据路由请求在路由视图中动态渲染对应的视图组件
- <router-link>:路由链接组件,浏览器会解析成<a>
- <router-view>:路由视图组件,用来展示与路由路径匹配的视图组件
index.js中维护路由
- App.vue,<router-link>标签生成超链接
<router-view>:路由视图组件不能删掉!!!
路由视图组件起到的是占位符的作用
3.3 路由跳转
有两种方式:
- 标签式
- 编程式
标签式就是上面演示的那种,编程式如下:
<template><div id="app"><nav><router-link to="/">Home</router-link> |<router-link to="/about">About</router-link><input type="button" value="编程式跳转" @click="jump()"></nav><!-- <router-view>:路由视图组件 --><router-view/></div>
</template><script>
export default {methods: {jump() {this.$router.push('/about')}}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}nav {padding: 30px;
}nav a {font-weight: bold;color: #2c3e50;
}nav a.router-link-exact-active {color: #42b983;
}
</style>
当用户输入的路径不对时,都会重定向到404页面,一张图告诉你如何重定向到不存在的页面:
4. 嵌套路由
嵌套路由是组件内要切换内容,就需要用到嵌套路由(子路由)
4.1 案例
以以下这个案例给大家分析:
实现步骤:
1)安装并导入elementui,实现页面布局(container布局容器)--ContainerView.vue
- 下载
使用命令下载elementui:npm i element-ui -S
- 在main.js中导入elementui
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 导入elementui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';Vue.config.productionTip = false
// 全局使用elementui
Vue.use(ElementUI);new Vue({router,render: h => h(App)
}).$mount('#app')
- 创建视图组件
<template><el-container><el-header>Header</el-header><el-container><el-aside width="200px">Aside</el-aside><el-main>Main</el-main></el-container>
</el-container>
</template><script>
export default {}
</script><style>.el-header, .el-footer {background-color: #B3C0D1;color: #333;text-align: center;line-height: 60px;}.el-aside {background-color: #D3DCE6;color: #333;text-align: center;line-height: 200px;}.el-main {background-color: #E9EEF3;color: #333;text-align: center;line-height: 160px;}body > .el-container {margin-bottom: 40px;}.el-container:nth-child(5) .el-aside,.el-container:nth-child(6) .el-aside {line-height: 260px;}.el-container:nth-child(7) .el-aside {line-height: 320px;}
</style>
- 在main.js中配置路由跳转
2)提供子视图组件,用于效果展示
- P1View.vue
<template><div>这是P1View</div>
</template><script>
export default {}
</script><style>
</style>
- P2View.vue
<template><div>这是P2View</div>
</template><script>
export default {}
</script><style>
</style>
- P3View.vue
<template><div>这是P3View</div>
</template><script>
export default {}
</script><style>
</style>
3)在src/router/index.js中配置路由映射规则(嵌套路由配置)
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'Vue.use(VueRouter)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: '/test',component: () => import( '../views/404View.vue')},{path: '/c',component: () => import( '../views/container/containerView.vue'),// 重定向到p1redirect: '/c/p1',children:[{path: '/c/p1',component: () => import( '../views/container/P1View.vue')},{path: '/c/p2',component: () => import( '../views/container/P2View.vue')},{path: '/c/p3',component: () => import( '../views/container/P3View.vue')}]},{path:"*",redirect: '/404'}
]const router = new VueRouter({routes
})export default router
4)在布局容器视图中添加<router-view>,实现子视图组件展示
<template><el-container><el-header>Header</el-header><el-container><el-aside width="200px">Aside</el-aside><el-main><!-- 占位符 --><router-view/></el-main></el-container>
</el-container>
</template>
5)在布局容器视图中添加<router-link>,实现路由请求
<template><el-container><el-header>Header</el-header><el-container><el-aside width="200px"><!-- 路由请求:生成超链接 --><router-link to="/c/p1">P1</router-link><br><router-link to="/c/p2">P2</router-link><br><router-link to="/c/p3">P3</router-link></el-aside><el-main><!-- 占位符 --><router-view/></el-main></el-container>
</el-container>
</template><script>
export default {}
</script><style>.el-header, .el-footer {background-color: #B3C0D1;color: #333;text-align: center;line-height: 60px;}.el-aside {background-color: #D3DCE6;color: #333;text-align: center;line-height: 200px;}.el-main {background-color: #E9EEF3;color: #333;text-align: center;line-height: 160px;}body > .el-container {margin-bottom: 40px;}.el-container:nth-child(5) .el-aside,.el-container:nth-child(6) .el-aside {line-height: 260px;}.el-container:nth-child(7) .el-aside {line-height: 320px;}
</style>
5. 状态管理vuex
5.1 介绍
- vuex是一个专门为Vue.js应用程序开发的状态管理库
- vuex可以在多个组件之间共享数据,并且共享的数据是响应式的,即数据的变更能即使渲染到模板
- vuex采用集中式存储管理所有组件的状态
5.2 vuex核心概念
5.3 使用方式
5.3.1 创建携带vuex的项目
- index.js
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)// 集中管理多个组件共享的数据
export default new Vuex.Store({state: {},getters: {},mutations: {},actions: {},modules: {}
})
- main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'Vue.config.productionTip = falsenew Vue({store, // 创建vuex实例render: h => h(App)
}).$mount('#app')
5.3.2 定义展示共享数据
5.3.3 在mutations中定义函数,修改共享数据
5.3.4 在actions中定义函数,用于调用mutation
// import { set } from 'core-js/core/dict'
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'Vue.use(Vuex)// 集中管理多个组件共享的数据
export default new Vuex.Store({// 共享数据state: {name:'未登录游客'},getters: {},// 修改共享数据只能通过mutation实现,必须是同步操作mutations: {setName(state, name){state.name = name}},// 封装异步操作,不能直接修改共享数据,只能通过mutation来实现actions: {setNameByAxios(context){axios({url:"/api/getUserInfo",method:"POST",data:{username:"admin",password:"123456"}}).then(res=>{if(res.data.code == 1){// 异步请求后,需要修改共享数据,只能通过mutation来实现// 在action中调用mutation中定义的setName方法context.commit("setName",res.data.username)}})}},modules: {}
})
在vue.config.js 配置重定向
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,devServer: {port: 8081,proxy: {// 将含有/api的字段重定向成 http://localhost:8080'/api': {target: 'http://localhost:8080',changeOrigin: true,pathRewrite: {// 重写路径,将含有/api的字段替换成 (空)'^/api': ''}}}}
})
6. TypeScript
6.1 TypeScript介绍
TypeScript是微软推出的开源语言
TypeScript是JavaScript的超集(js有的ts都有)
TypeScript在js基础上做了类型支持
TypeScript文件扩展名为ts
TypeScript可编译成标准的JavaScript,并且在编译时进行类型检查
6.2 TypeScript常用类型
6.2.1 创建携带TypeScripe的项目
类型标注的位置:
- 标注变量
- 标注参数
- 标注返回值
6.2.2 字符串类型、数据类型、布尔类型
// 字符串类型
let str: string = 'I LOVE YOU 1314';// 数字类型
let num: number = 1314;// 布尔类型
let bool: boolean = true;console.log(str, num, bool);console.log("-------------------------");// 字面量类型
function printTest(s:string,alignment:'left'|'center'|'right'){console.log(s,alignment)
}
// 调用函数
printTest('I LOVE YOU 1314','left');console.log("-------------------------");// interface 接口类型
interface Cat{name:string;// ? 可选属性age?:number;
}
// 定义变量,并且指定为Cat类型
const c1:Cat = {name:'Tom',age:10}
const c2:Cat = {name:'Tom'}console.log("-------------------------");// class类 - 基本使用
class User{name:string;constructor(name:string){this.name = name;}study(){console.log('I am '+this.name);}
}
// 使用User类型
const user = new User('Tom');// 输出类中的属性
console.log(user.name);// 调用类中的方法
user.study();console.log("-------------------------");// class类 - 实现接口
interface Animal{name:string;eat():void;
}// 定义一个类实现Animal接口
class Bird implements Animal{name:string;constructor(name:string){this.name = name;}eat():void{console.log('I am eating');}
}
// 创建类型为Bird的对象
const bird = new Bird('小鸟');
console.log(bird.name);
bird.eat();// class类 - 继承Bird类
class Parrot extends Bird{say(){console.log(this.name+' can say');}
}
const parrot = new Parrot('鹦鹉');
console.log(parrot.name);
parrot.eat();
parrot.say();