Vue2
Vue2
环境准备
安装脚手架
npm install -g @vue/cli
创建项目
vue ui //新建项目界面
。使用图形向导来创建 vue 项目,记得要勾选router 和 vuex
安装 devtools
devtools插件网址:https://devtools.vuejs.org/guide/installation.html

运行项目
npm run serve
修改端口
文档地址:DevServer | webpack
https://webpack.js.org/configuration/dev-server/#devserverproxy

。打开 vue.config.js 添加
const { defineconfig }=require('@vue/cli-service')
module.exports= defineconfig({
devserver: {port:7070}
})
添加代理
const{defineConfig }=require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies:true,
devServer:{
port: 7070,
proxy:{'/api':
{
target:'http://localhost:3000'
,changeorigin:true
}
}
}
}
Vue项目结构
PS D:\2022.js\代码\第3章\client>tree src
D:\2022.JS\代码\第3章\CLIENT\SRC
|-assets
|-components
|-router
|-store
|-views
。assets-静态资源
。components-可重用组件
·router-路由
。store-数据共享
。views-视图组件
以后还会添加
。api-跟后台交互,发送fetch、xhr 请求,接收响应
plugins-插件
Vue组件
Vue 的组件文件以 .vue 结尾,每个组件由三部分组成
<template></template>
<script></script>
<sty1e></style>
。template 模板部分,由它生成 html 代码。
script 代码部分,控制模板的数据来源和行为
。style 样式部分
App.vue 注意顶层元素只能有一个!!!!!!!!!!
<temnlate>
<div>
<h1>{{msg}}</h1>
<h1>{{age > 18?'老年':'青年'}}</h1)
</div>
</template>
<script>
const options ={
data: function(){
return {msg:'你好!',age:18};
}
}
export default options;
</script>
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new vue({
router,
store,
render:h=>h(App)}).$mount('#app')
index.html
<!DOCTYPE htm1><html lang=""
<head>
<meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=<meta
name="viewport" content="width=device-widt<link rel="icon" href="<%= BASE URL
%>favicon.ic<title><%= htmlWebpackPlugin.options.title %></i</head>
<body>
<noscript>
<strong>We're sorry but
<%= htmlWebpackPlugin</noscript>
<div id="app"><!--这里是渲染的id-->
</div>
<!--built files will be auto
</body>
</html>
Vue绑定
vuetools在浏览器的vue导航可以看到vue里面的数据
<template>
<div>
<div><input type="text" v-bind:value="name"></div>
<div><input type="date" v-bind:value="birthday"></div>
<div><input type="text" :value="age"></div>
<input type="button" value=”点我" v-on:click="m1">
<input type="button" value=”点我" @click="m1">
<label for=">请输入姓名</1abe1>
<input type="text” v-model="name" />
<!-- v-model双向绑定,只用于表单,v-model默认和value绑定,不用写属性名-->
<div>
<label for="">请选择性别</label>男
<input type="radio" value="男"v-model="sex">女
<input type="radio" value="女”v-model="sex">
</div>
<div>
<label for="">请选择爱好</label>
游泳<input type="checkbox" value="游泳”v-model="fav">
打球<input type="checkbox" value="打球”v-model="fav">
健身<input type="checkbox” value="健身”v-model="fav">
</div>
<h2>{{lastName + firstName}}</h2>
<h2>{{fullName()}}</h2><!--多个使用methods的会重复计算-->
<h2>{{fullName}}</h2><!--多个使用computed不会重复计算,提升性能-->
<!--if与for不能同一个标签-->
<div v-if="students.length >o"
<div class="row" v-for="s of students" :key="s.id">
<div class="col">{{s.id}}</div>
<div class="col">{{s.name}}</div>
<div class="col">{{s.sex}}</div>
<div class="col">{{s.age}}</div>
</div>
</div>
<div class="row" v-else>暂无学生数据</div>
</div>
</template>
<script>
const options ={
data:function(){
return{ name:'王五',birthday:'1995-05-01',age: 20,sex:'男',fav:[]
,firstName :'三',lastName:'张'};
}
methods:{
m1(){
console.log(“m1")
},
m2(){
console.log("m2")
}
fullName(){
return this.lastName + this.firstName;
}
},
computed:fullName(){
return this.lastName + this.firstName;
}
//页面加载完时执行
mounted: function(){this.sendReq())} I
}
export default options;
</script>
axios
axios 它的底层是用了 XMLHttpRequest(xhr)方式发送请求和接收响应,xhr相对于之前讲过的 fetch api来说,功能更强大,但由于是比较老的 api,不支持 Promise,axios 对xhr进行了封装,使之支持 Promise,并提供了对请求响应的统一拦截功能
安装
npm install axios -s
创建实例
const _axios = axios.create(config);
。config 见后面说明
方法
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.pdst(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
axios.request(config)
config-选项对象、例如查询参数、请求头..
data-请求体数据、最常见的是json 格式数据
get、head 请求无法携带请求体,这应当是浏览器的限制所致(xhr、fetchapi均有限制)
options、delete 请求可以通过 config 中的 data 携带请求体
<template>
<div>
<input type="button" value="获取远程数据”@click="sendReg()">
</div>
</template>
<script>
import axios from 'axio’
const options ={
methods:{
async sendReq(){
const resp= await axios.get('/api/students');
console.log(resp);
// 1.演示 get,post
// const resp= await axios.post('/api/a2');
// 2.发送请求头
// const resp= await axios.post('/api/a3',{},{
headers:{Authorization:'abc'}});
// 3.发送请求时携带查询参数 ?name=xxx&age=xxx
//const name =encodeURIcomponent('&&&');
//const age =18;
//const resp=await axios.post( /api/a4?name=${name)&age=${age}
//不想自己拼串、处理特殊字符、就用下面的办法
const resp=await axios.post('/api/a4',{},{params:{
name:'&&&&',
age:20
});
console.log(resp);
//4.用请求体发数据,格式为urlencoded
// const params = new URLSearchParams();
// params.append("name","张三");
// params.append("age",24)
// const resp=await axios.post('/api/a4',params)
//5.用请求体发数据,格式为multipart
const params =new FormData();
params.append("name","李");
params.append("age",30);
const resp= await axios.post('/api/a4',params);
console.log(resp);
//6.用请求体发数据,格式为json
const resp = await axios.post('/api/a5jso',{
name:'王五'
age:50
});
// JsoN.stringify
console.log(resp);
}
}
export default options;
</script>
创建实例
const _axios = axios.create(config);
。axios 对象可以直接使用,但使用的是默认的设置。
用 axios.create 创建的对象,可以覆盖默认设置,config 见下面说明
名称 | 含义 |
---|---|
baseURL | 将自动加在 url 前面 |
headers | 请求头,类型为简单对象 |
params | 跟在 URL 后的请求参数,类型为简单对象或 URLSearchParams |
data | 请求体,类型有简单对象、FormData、URLSearchParams、File 等 |
withCredentials | 跨域时是否携带 Cookie 等凭证,默认为 false |
responseType | 响应类型,默认为 json |
const _axios = axios.create({
baseURL:'http://localhost:8080',
withCredentials:true
});
await _axios.post('/api/a6set',{})
await _axios.post('/api/a6get',{})
//8.响应格式
try{
const resp=await _axios.get('/api/students')
console.log(resp)
} catch(e){
console.log(e.response)
}
//java配置
@CrossOrigin(value = "http://localhost:7070", allowcrydentials = "true")
PostMapping("/api/a6set")
public string a6set(HttpSession session){
System.out.println("========== a6 set ==========");
System.out.println(session.getId())
session.setAttribute( name:"name","张三");
return "post request";
}
@PostMapping("/api/a6get")
public string a6get(HttpSession session){
System.out.println("========== a6 get ==========")
System.out.println(session.getId());
System.out.println("name:"+ session.getAttribute( name: "name"));
return "post request";
}
@0verride
public void addcorsMappings(corsRegistry registry){
registry.addMapping("/**")
.allowedorigins("http://localhost:7070")
.allowCredentials(true);
}
名称 | 含义 |
---|---|
data | 响应体数据 ⭐ |
status | 状态码 ⭐ |
headers | 响应头 |
200 表示响应成功
400 请求数据不正确
401 身份验证没通过
403 没有权限
404 资源不存在
405 不支持请求方式
500 服务器内部错误
axios拦截器
请求拦截器
axios.interceptors.request.use(
function(config){
//比如在这里添加统一的 headers
config.headers = {Authorization:'aaa.bbb.ccc}
return config;
}
function(error){
return Promise.reject(error)
);
}
响应拦截器
_axios.interceptors.response.use(
function(response){
if(error.response.status ===400){
console.1og('请求参数不正确');
}
else if(error.response.status === 401){
console.1og('跳转至登录页面’);
}
// 2xx 范围内走这里
return response;
}
function(error){
//超出 2xx,比如 4xx,5xx 走这里
return Promise.reject(error);
}
父子组件
子组件
<template>
<div class="button" :class="[type,size]>
a<slot></slot>b<!--显示父组件标签中间值-->
</div>
</template>
<script>
const options ={
props: ["type","size"]
};
export default options;
</script>
<!--重用组件-->
<template>
<div>
<h1>父组件</h1>
<my-button type="primary" size="small">1</my-button>
<my-button>2</my-button>
<my-button>3</my-button>
<my-button>4</my-button>
</div>
</template>
<script>
import MyButton from '../components/MyButton.vue'
const options ={
components:{
MyButton
}
export default options;
</script>
ElementUl
安装
npm install element-ui -s
引入组件
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(Element)
测试
<e1-button>按钮</e1-button>
Vue-Router
vue 属于单页面应用,所谓的路由,就是根据浏览器路径不同,用不同的视图组件替换这个页面内容展示
example14.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import ContainerView from '@/views/example14/ContainerView.vue'
import Loginview from '@/views/example14/LoginView.vue'
import NotFoundView from '@/views/example14/NotFoundView.vue'
Vue.use(VueRouter)
const routes =[
{
path:'/',
component:ContainerView
redirect:'/c/p1'//重定向到。。
children:[
{
path:'c/p1',
...
}
]
},
{
path:'/login',component:LoginView
},
{
//匹配不到则404
path:'*'',redirect:'/404'
}
{
//动态按需加载提升性能
path:'/404',component:()=>import('@/views/example14/NotFoundView.vue')
},
]
const router = new VueRouter({routes})
export default router
main.js
import router from './router/example14'
new Vue({
router,store,render:h=>h(e14)
}).$mount('#app')
Example14View.vue
<template>
<div class="all">
<router-view></router-view>
<!--点击这个使得router-view替换-->
</router-link to="/c/p1">P1</router-link>
</div>
</template>
@click=jump('c/p1');
methods:{
jump(url){
this.$router.push(url);
}
}
Vuex
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//读取数据,走 state,getters
//修改数据,走 mutations,actions
export default new Vuex.store({
state:{
name:'',
},
getters:{},
mutations:{
updateName(state,name){
state.name =name;
}
}
actions:{},
modules:{}
})
this.$store.commit('updateName', this.name);
{{$store.state.name}}
简写
computed:{
name(){
return this.$store.state.name
}
}
欢迎您:{{name}}
多个参数
computed:mapState(['name','age'])
或者
computed:{
...mapState(['name','age'])
}
import {mapMutations} from'vuex'
console.log(mapMutations(['updateName']))
methods:{
...mapMutations(['updateName'])
}
@click="updateName(name)"