跳至主要內容

Vue2

HeChuangJun约 1935 字大约 6 分钟

Vue2

环境准备

安装脚手架
npm install -g @vue/cli
创建项目

vue ui //新建项目界面

。使用图形向导来创建 vue 项目,记得要勾选router 和 vuex

1.png
2.png
3.png
4.png

安装 devtools

devtools插件网址:https://devtools.vuejs.org/guide/installation.htmlopen in new window

5.png
5.png

运行项目

npm run serve

修改端口

文档地址:DevServer | webpack

https://webpack.js.org/configuration/dev-server/#devserverproxyopen in new window

6.png
6.png
。打开 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)"