Vue组件的定义、注册方式和模板使用
组件的定义
组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码.
vue组件是把页面(html代码,CSS代码)进行模块化
如下图所示,一个页面分四个部分,每个部分是个vue组件,而页面成了vue组件的容器。
vue.js中创建组件有三个步骤:定义组件,注册组件以及使用组件
定义组件
定义组件名的方式有两种:
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>
。当使用 PascalCase (驼峰式命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name>
和 <MyComponentName>
都是可接受的。
组件的分类
引用模版
将组件内容放到<template>
中引用。
注意:template组件中,有且只有一个根元素
代码示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>全局组件和局部组件</title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app1">
<h1>{{message}}</h1>
<!-- 使用全局组件 -->
<global-componet-a></global-componet-a>
</div>
<div id="app2">
<h1>{{message}}</h1>
<!-- 使用全局组件 -->
<global-componet-a></global-componet-a>
</div>
<div id="app3">
<h1>{{message}}</h1>
<!-- 使用全局组件 -->
<global-componet-a></global-componet-a>
<!-- 使用局部组件 -->
<component-a></component-a>
</div>
</body>
<!-- 定义模板 -->
<template id="my-temlate-1">
<div><h3>{{info}}</h3><a href='http://www.baidu.com'>百度</a></div>
</template>
<script type="text/javascript">
//全局组件定义和注册 Vue.componet("全局组件名称",{})
Vue.component("global-componet-a",{
//定义的数据属性要用函数返回对象(对象中存储数据),因为组件每次使用都是一个独立的对象实例,
//如果data使用原来的方式还是返回的是对象,不调用函数,那么组件每个实例使用的是同一个data属性对象,使用组件的每个实例,共享data属性数据对象实例,是不可以的
data:function(){
return {
info:"全局组件"
}
},
//使用的是模板,使用模板id或者模板放入html标签
template:"#my-temlate-1"
});
var app1 = new Vue({
el:"#app1",
data:{
message:"vue-1调用全局组件"
}
});
var app2 = new Vue({
el:"#app2",
data:{
message:"vue-2调用全局组件"
}
});
var app3 = new Vue({
el:"#app3",
data:{
message:"vue-3调用全局组件全局组件和局部组件"
},
//局部组件定义和注册,使用范围只能在app3挂载的DOM对象中
components:{
"component-a":{
data:function(){
return {info:"局部组件"}
},
//使用的是模板,使用模板id或者模板放入html标签
template:"#my-temlate-1"
}
}
});
</script>
</html>
组件间数据的通信
父子组件
在一个组件内部定义另一个组件,称为父子组件
子组件只能在父组件内部使用
默认情况下,子组件无法访问父组件中的数据,每个组件实例的作用域是独立的
组件间数据通信
子组件访问父组件的数据(父传子)
props传递数据两种形式
- 数组方式: props:[‘msg’, ‘username’, ‘age’, ‘userObj’]
- 对象方式:该方式提供了对数据的校验、类型监测、默认值设置操作。
prop命名,可以在在组件中使用postTitle
(驼峰名称),在html中是使用短横线命名post-title
,如下代码示例
Vue.component('blog-post', {
// 在 JavaScript 中是 驼峰命名 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 短横线 的 -->
<blog-post post-title="hello!"></blog-post>
父组件传子组件的代码实例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 调用根实例message属性值 -->
<h1>{{message}}</h1>
<!-- 使用子组件 -->
<!-- 使用v-bind的简写方法绑定属性 parent-message 值为根实例(父组件)的data属性数据 message-->
<component-a :parent-message="message"></component-a>
</div>
</body>
<!-- 定义模板 -->
<template id="my-temlate-1">
<div>
<!-- 使用data中的数据 -->
<h3>子组件内部数据(child-message):{{childMessage}}</h3>
<!-- 使用props中的数据 -->
<h3>子组件外部数据(props-parentMessage):{{parentMessage}}</h3>
</div>
</template>
<script type="text/javascript">
//定义子组件
var componentA = {
data:function(){
return {
childMessage:"我是子组件的message属性值"
}
},
props:["parentMessage"], //定义props属性对象(数组)
template:"#my-temlate-1" //使用模板
}
var app = new Vue({
el:"#app",
data:{
message:"我是(Vue根实例)父组件的message属性值"
},
//注册子组件
components:{
//格式 "子组件名称":定义的子组件对象
"component-a":componentA
}
});
</script>
</html>
父组件访问子组件的数据(子传父)
- 第一步:在子组件中使用 vm.$emit(事件名,数据) 触发一个自定义事件,事件名自定义。
- 第二步:父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据。
- 总结:子组件通过events(事件)给父组件发送消息,实际上就是子组件把自己的数据发送到父组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用子组件 itemclick为子组件自定义的事件名称,绑定父组件的函数-->
<component-a @itemclick="parentclick"></component-a>
</div>
</body>
<!-- 定义模板 -->
<template id="my-temlate-1">
<div>
<!-- 使用v-bind简写方式绑定属性value的值 ,使用v-on简写方式绑定click是事件-->
<input type="button" v-for="item in categories" :value="item.name" @click="btnclick(item)" />
</div>
</template>
<script type="text/javascript">
//定义组件
var componentA={
data:function() {
return {
categories:[
{id:1,name:"家电"},
{id:2,name:"玩具"},
{id:3,name:"数码"},
{id:4,name:"服装"},
]
}
},
//注册模板
template:"#my-temlate-1",
methods:{
btnclick:function(item){
//alert(item.id);
//子组件向父组件发出自定义事件(自定义事件名称,自定义事件参数)
this.$emit("itemclick",item);
}
}
}
var app = new Vue({
el:"#app",
//注册局部子组件
components:{"component-a":componentA},
methods:{
parentclick:function(item){ //可以获取子组件传过来的参数item
alert("我是父组件,子组件id="+item.id);
}
}
});
</script>
</html>
非父子通信
创建一个Vue实例作为中央事件总线,通过它来监听(
o
n
)
和
触
发
(
on)和触发(
on)和触发(emit)事件。适用于组件间全部通信方式。
//实例Vue实例作为中央事件总线
var Event=new Vue();
//发送事件
Event.$emit(事件名,数据);
//监听事件
Event.$on(事件名,data => {});
假设兄弟组件有三个,分别是 A、B、C 组件,C 组件如何获取 A 或者 B 组件的数据
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 引入vue.js -->
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="app">
<my-a></my-a>
<my-b></my-b>
<my-c></my-c>
</div>
</body>
<template id="a">
<div>
<h3>A组件:{{name}}</h3>
<button @click="send">将数据发送给C组件</button>
</div>
</template>
<template id="b">
<div>
<h3>B组件:{{age}}</h3>
<button @click="send">将数组发送给C组件</button>
</div>
</template>
<template id="c">
<div>
<h3>C组件:{{name}},{{age}}</h3>
</div>
</template>
<script type="text/javascript">
var Event = new Vue();//定义一个空的Vue实例
var A = {
template: '#a',
data() {
return {
name: 'tom'
}
},
methods: {
send() {
Event.$emit('data-a', this.name);
}
}
}
var B = {
template: '#b',
data() {
return {
age: 20
}
},
methods: {
send() {
Event.$emit('data-b', this.age);
}
}
}
var C = {
template: '#c',
data() {
return {
name: '',
age: ""
}
},
mounted() {//在模板编译完成后执行
Event.$on('data-a',name => {
this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
})
Event.$on('data-b',age => {
this.age = age;
})
}
}
var app = new Vue({
el: '#app',
components: {
'my-a': A,
'my-b': B,
'my-c': C
}
});
</script>
</html>
总结组件之间的通讯
单向数据流
props是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来,即子组件中使用的父组件数据发生变化,无法传导给父组件。而且不允许子组件直接修改父组件中的数据,会直接报错,这样更有利于组件间的解耦
解决方式:
- 方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据。
- 方式2:如果子组件想修改数据并且同步更新到父组件
- 可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间),推荐使用。
过滤器
过滤数据是我们日常开发中必然会用到的。
常见的场景:当我们从后端请求到数据列表时,我们需要对其中符合条件的数据进行筛选、当我们拿到数据,我们希望把英文首字母大写,等等。
过滤器分为两种:
- 单个组件的过滤器,也叫做局部过滤器,
- vue实例全局的过滤器,它可以被应用在任何地方。
过滤器使用地方两个位置:
-
{{ message | filterA }}
双括号插值内
-
<h1 v-bind:id="message | filterA">{{ message }}</h1>
v-bind绑定的值的地方
过滤器也可以使用多个,会依次执行:
例如:{{ message | filterA |filterB }}
这个例子中会把message 的当做参数传入A过滤器进行过滤,A过滤器过滤完的数据返回值会传入B过滤器
全局过滤器:Vue.filter(“过滤器名称”,函数);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="app1">
<h1>我是app1:{{message | upperCase}}</h1>
</div>
<div id="app2">
<h1>我是app2: {{message | upperCase}}</h1>
</div>
</body>
<script type="text/javascript">
//定义全局过滤器
Vue.filter("upperCase",function(value){
if(!value) return "";
value = value.toString();
//字符转换成大写
return value.toUpperCase();
});
var app1 = new Vue({
el:"#app1",
data:{
message:"HelloWord"
}
});
var app2 = new Vue({
el:"#app2",
data:{
message:"hahahaha"
}
});
</script>
</html>
局部过滤器:定义局部的过滤器 定义格式:fliters:{过滤器名称:函数}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="app3">
<component-a :msg="message"></component-a>
</div>
</body>
<!-- 定义模板 -->
<template id="my-temlate-1">
<h3>我是子组件,使用了局部过滤器{{msg|capitalize}}</h3>
</template>
<script type="text/javascript">
//定义组件
var componentA = {
props:["msg"],
template:"#my-temlate-1",
//定义局部过滤器,注意是filters
filters:{
//过滤器名称:函数
capitalize:function(value){
if(!value) return "";
value = value.toString();
value = value.charAt(0).toUpperCase()+value.substring(1); //首字母大写
return value;
}
}
}
var app3=new Vue({
el:"#app3",
data:{
message:"ddddd"
},
components:{
"component-a":componentA //注册局部组件
}
});
</script>
</html>
路由
定义
路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容。
分类
后端路由
例如,分配一个站点,服务器地址是:http://192.168.1.200:8899
,在这个网站中提供了三个界面
http://192.168.1.200:8899/index.html 主页
http://192.168.1.200:8899/about/about.html 关于我们页面
http://192.168.1.200:8899/feedback.html 反馈界面
当我们在浏览器输入 http://192.168.1.200:8899/index.html
来访问界面的时候,web 服务器就会接收到这个请求,然后把 index.html 解析出来,并找到相应的 index.html 并展示出来,这就是路由的分发,路由的分发是通过路由功能来完成的
前端路由
1、虽然前端路由和后端路由的实现方式不一样,但是原理都有是相同的,其中一个方式
前端路由的功能都是通过 hash 「散列值」 来实现的,hash 能兼容低版本的浏览器
2、后端路由每次仿问一个页面都要向浏览器发送请求,然后服务端再响应解析,在这个过程中肯定会存在延迟,但是前端路由中仿问一个新的界面的时候只是浏览器的路径改变了,没有和服务端交互「所以不存在延迟」,这个对用户体验来说是大大的提高。如下所示:
http://192.168.1.200:8080/#/index.html
http://192.168.1.200:8080/#/about/about.html
http://192.168.1.200:8080/#/feedback.html
由于 web 服务器不会解析 # 后面的东西「所以通过 hash 能提高性能」,但是客户端的 js 可以拿到 # 后面的东西,有一个方法是 window.location.hash 来读取,使用这个方法来匹配到不同的方法上
3、举个例子
http://www.xxx.com/path/a/b/c.html?key1=Tiger&key2=Chain&key3=abc#/path/d/e.html
我们把这个地址分析一下
http:协议
www.xxx.com:域名
/path/a/b/c.html:路由,即服务器上的资源
?key1=Tiger&key2=Chain&key3=abc:这 Get 请求的参数
#/path/d/e.html:hash 也叫散列值,也叫锚点
上面的 hash 是和浏览器交互的,其它的都是和服务器进行交互
Vue 路由
Vue 中的路由,推荐使用官方支持的 vue-router 库
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/vue-router-3.5.1.js"></script>
</head>
<body>
<div id="app">
<!-- 打印mine变量是构造函数 -->
<input type="button" value="打印mine变量" @click="method1" />
<!-- router-link 显示成超链接 -->
<router-link to="/main">main</router-link>
<router-link to="/message">message</router-link>
<router-link to="/mine">mine</router-link>
<!-- 路由对应的内容在这里显示-->
<router-view>
</router-view>
</div>
</body>
<!-- 定义模板 -->
<template id="t_main">
<div style="height: 400px;width: 400px;background-color: green;">
{{title}}
</div>
</template>
<template id="t_message">
<div style="height: 400px;width: 400px;background-color: red;">
{{title}}
</div>
</template>
<template id="t_mine">
<div style="height: 400px;width: 400px;background-color: yellow;">
{{title}}
</div>
</template>
<script type="text/javascript">
//Vue.extend 使用基础 Vue 构造器函数,通过原型继承,(返回)创建一个“子类”(构造器), 这里只是构造函数 但是还没有实例化所以还不是一个组件对象
//定义组件构造器main
var main = Vue.extend({
data:function(){
return {
title:"主页"
}
},
template:"#t_main"
});
//定义组件构造器message
var message = Vue.extend({
data:function(){
return {
title:"消息"
}
},
template:"#t_message"
});
//定义组件构造器mine
var mine = Vue.extend({
data:function(){
return {
title:"我的"
}
},
template:"#t_mine"
});
//路由routes配置规则对象
var routes = [
//path 是url路径 component是路径所对应的组件构造器或者组件对象
{path:"/",component:main},
{path:"/main",component:main},
{path:"/message",component:message},
{path:"/mine",component:mine}
]
//实例化一个VueRouter对象,routes对象赋值给VueRouter实例对象routes属性
var router = new VueRouter({
routes //相当于routes:routes 如果属性名和属性值相同,可以只写一个名称
});
var app = new Vue({
el:"#app",
//VueRouter对象赋值router属性
router, //相当于 router:router
methods:{
method1:function(){
/* 打印mine变量 */
console.log(mine);
}
}
});
</script>
</html>
嵌套路由
实际应用界面,通常由多层嵌套的组件组合而成,比如,我们 “首页”组件中,还嵌套着 “登录”和 “注册”组件,那么URL对应就是/home/login和/home/register
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/vue-router-3.5.1.js"></script>
</head>
<body>
<div id="app">
<p>
<router-link to="/home">首页</router-link>
<router-link to="/news">新闻</router-link>
</p>
<router-view></router-view>
</div>
</body>
<!-- 定义模板 -->
<template id="home">
<div>
<h2>{{title}}</h2>
<!-- //通过query配置路由参数 key为query 参数为JSON对象,请求的结果为 #/home/login?id=1 -->
<router-link :to="{path:'/home/login',query:{id:1}}">登录</router-link>
<router-link :to="{name:'register',params:{'name':'zhangsan'}}">注册</router-link>
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
</template>
<template id="news">
<div><h2>{{title}}</h2></div>
</template>
<template id="login">
<!-- this.$route.query.id 获取url传参数得值 -->
<div><h3>{{title}},{{this.$route.query.id}}</h3></div>
</template>
<template id="register">
<!-- this.$route.params.name 获取url传参数得值 -->
<div><h3>{{title}},{{this.$route.params.name}}</h3></div>
</template>
<script type="text/javascript">
//定义组件
var componentHome = {
data:function(){
return{
title:"首页"
}
},
template:"#home"
}
var componentNews = {
data:function(){
return{
title:"新闻"
}
},
template:"#news"
}
var componentLogin = {
data:function(){
return{
title:"登录"
}
},
template:"#login"
}
var componentRegister = {
data:function(){
return{
title:"注册"
}
},
template:"#register"
}
//配置路由(嵌套路由,componentHome,有children配置,就是嵌套路由)
var routes = [
//redirect 跳转url,如下当访问 / 跳转到 /home 这个路径
{path:"/",redirect:"/home"},
{path:"/home",component:componentHome,children:[
{path:"/home/login",component:componentLogin},
//path路径使用:参数名 占位,在router-link配置中使用params:{'参数名':'参数值'} 补位
{path:"/home/register/:name",component:componentRegister,name:"register"},
]},
{path:"/news",component:componentNews},
]
var router = new VueRouter({routes});
var app = new Vue({
el:"#app",
router
});
</script>
</html>
使用axios进行ajax操作
Axios简介
vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现。
axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护。
参考:GitHub上搜索axios,查看API文档 https://github.com/axios/axios
Axios特点
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。本质上也是对原生XHR(XmlHttpRequest)的封装,只不过它是Promise 的实现版本,符合新的ES规范,有如下特点:
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换 JSON 数据
客户端支持防御 XSRF
Axios基本用法
axios({options})
axios.get(url,{options});
GET传参方式:
1.通过url传参
2.通过params选项传参
POST传参方式:
axios.post(url,data,{options});
默认情况下,axios将JavaScript对象序列化为JSON。要以application / x-www-form-urlencoded格式发送数据,您可以使用以下选项之一。
传参方式:
1.自己拼接为键值对
2.使用transformRequest,在请求发送前将请求数据进行转换
3.如果使用模块化开发,可以使用qs模块进行转换
Vue中axios中箭头函数的this和function(response)函数体中的this的区别
1、在methods下的函数this指向的是当前创建的vue实例,
2、axios与后台交互后回调函数的内部的this指向window而并非指向当前的vue实例,
3、若想拿到后台回传的数据更新data里的数据,不能在回调函数中直接使用this,要用外部函数定义的变量(如:_this)存储的this,也就是当前vue的实例。
4、使用箭头函数之后,箭头函数指向的函数内部的this已经绑定了外部的vue实例了
Axios的get请求代码示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/axios-0.21.1.js"></script>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<input type="button" value="axiox请求1(get)" @click="sendAxiosGet1()"/>
<input type="button" value="axiox请求2(get)" @click="sendAxiosGet2()"/>
<input type="button" value="axiox请求3(get)" @click="sendAxiosGet3()"/>
<table border="1px" cellspacing="0px">
<tr>
<td>编号</td>
<td>姓名</td>
<td>年龄</td>
<td>邮箱</td>
</tr>
<hr/>
<tr v-for="student in students">
<td>{{student.id}}</td>
<td>{{student.name}}</td>
<td>{{student.age}}</td>
<td>{{student.email}}</td>
</tr>
</table>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
message:"axios的ajax请求",
students:[{id:1,name:"zhansan",age:18,email:"aa@qq.com"}]
},
methods:{
//ajax使用语法:axios({}).then().catch(),then() 表示ajax请求成功后,处理服务器响应数据, catch() 表示ajax请求异常或者失败,处理异常或者失败情况
sendAxiosGet1:function(){
var _this = this; //这里的this是Vue对象
axios({
method:"get", //请求方式 get/post
url:"http://rap2api.taobao.org/app/mock/238982/students", //请求的服务器url地址
params:{}, //请求的数据参数
reponseType:"json" , //服务器相应数据的类型
reponseEncoding:"utf-8" //服务器响应数据的编码格式
}).then(function(response){ //ajax请求成功后,处理服务器响应数据
console.log(response);
console.log(response.data);
//打印this
console.log(this); // 这里的this表示window对象,不是我们想要的Vue对象实例
console.log(_this); // _this表示Vue对象实例
_this.students = response.data.students // 服务端返回的数据赋值给属性students,页面就展示了数据
}).catch(function(e){
console.log(e);
alert(e);
});
},
sendAxiosGet2:function(){
var _this = this; //这里的this是Vue对象
axios({
method:"get",
url:"http://rap2api.taobao.org/app/mock/238982/students", //请求的服务器url地址
params:{p1:"A",p2:"B"}, //请求的数据参数
reponseType:"json" , //服务器相应数据的类型
reponseEncoding:"utf-8" //服务器响应数据的编码格式
}).then((response)=>{ //ajax请求成功后,处理服务器响应数据 ,ES6的语法 箭头函数,可以解决this的指向问题
console.log(response);
console.log(response.data);
//打印this
console.log(this); // 这里的this表示的Vue对象实例
this.students = response.data.students // 服务端返回的数据赋值给属性students,页面就展示了数据
}).catch(function(e){
console.log(e);
alert(e);
});
},
//axios的get方法 axios.get(url,{}).then().catch();
sendAxiosGet3:function(){
axios.get("http://rap2api.taobao.org/app/mock/238982/students",{
params:{p1:"A",p2:"B"}, //请求的数据参数
reponseType:"json" , //服务器相应数据的类型
reponseEncoding:"utf-8" //服务器响应数据的编码格式
}).then((response)=>{
this.students = response.data.students // 服务端返回的数据赋值给属性students,页面就展示了数据
}).catch((e)=>{
console.log(e);
alert(e);
});
}
}
});
</script>
</html>
Axios的post请求和传参方式代码示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/axios-0.21.1.js"></script>
<script type="text/javascript" src="js/qs-6.10.1.js"></script>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<input type="button" value="axiox请求4(post)" @click="sendAxiosPost1()"/>
<input type="button" value="axiox请求5(post)" @click="sendAxiosPost2()"/>
<table border="1px" cellspacing="0px">
<tr>
<td>编号</td>
<td>姓名</td>
<td>年龄</td>
<td>邮箱</td>
</tr>
<hr/>
<tr v-for="student in students">
<td>{{student.id}}</td>
<td>{{student.name}}</td>
<td>{{student.age}}</td>
<td>{{student.email}}</td>
</tr>
</table>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
message:"axios的ajax请求",
students:[{id:1,name:"zhansan",age:18,email:"aa@qq.com"}]
},
methods:{
//ajax使用语法:axios({}).then().catch(),then() 表示ajax请求成功后,处理服务器响应数据, catch() 表示ajax请求异常或者失败,处理异常或者失败情况
//axios的post请求
sendAxiosPost1:function(){
axios({
url:"http://192.168.60.254:8080/20210623/student/list",//请求服务器的url
method:"post",//请求方式
// `data` 是作为请求主体被发送的数据 data用于post、put、patch请求
data:{p1:"A",p2:"B"},//默认情况下,axios-post请求请求参数data对象序列化为JSON
responseType:"json", //服务器响应数据类型
responseEncoding:"utf-8" //服务器响应数据编码
}).then((response)=>{
this.students = response.data.students;
}).catch((e)=>{
console.log(e);
alert(e);
});
},
//axios的post请求
sendAxiosPost2:function(){
axios({
url:"http://192.168.60.254:8080/20210623/student/list",//请求服务器的url
method:"post",//请求方式
//headers 设置请求头类型
//Content-Type的默认类型是application/json
headers:{"Content-Type":"application/x-www-form-urlencoded"},
// `data` 是作为请求主体被发送的数据 data用于post、put、patch请求
// 要以applicaton/x-www-form-urlencoded格式发送数据
//Qs.stringify方法把json对象序列化成url形式,以&拼接
data:Qs.stringify({p1:"A",p2:"B"}),
responseType:"json", //服务器响应数据类型
responseEncoding:"utf-8" //服务器响应数据编码
}).then((response)=>{
this.students = response.data.students;
}).catch((e)=>{
console.log(e);
alert(e);
});
},
//axios.post(url,data,{}).then().catch() data表示数据
sendAxiosAjaxPost3: function() {
//Qs.stringify() 把json对象序列化url格式,用&连接 p1=A&p2=B
var paramData = Qs.stringify({
p1: "A",
p2: "B"
});
axios.post("http://192.168.60.254:8080/20210623/student/list", paramData, {
// post默认是 参数类型json,服务器要支持json数据格式,希望请求参数 form类型 application/x-www-form-urlecoded
//设置请求头 请求的数据类型为 application/x-www-form-urlecoded
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
responseType: "json", //服务端响应的数据类型
responseEncoding: "UTF-8" //服务端响应数据的编码
}).then(response => {
console.log(response);
this.students = response.data.students;
}).catch(e => {
console.log(e);
alert(e);
});
}
}
});
</script>
</html>
后端代码:
@WebServlet(urlPatterns = {"/student/list"})
public class StudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String p1 = req.getParameter("p1");
String p2 = req.getParameter("p2");
System.out.println("p1=" + p1 + ",p2=" + p2);
//设置响应数据格式和编码
resp.setContentType("application/json;charset=utf-8");
//允许跨域请求(后台允许跨域请求)
resp.setHeader("Access-Control-Allow-Origin", "*");
//获取数据
List<Student> students = getStudents();
Result result = new Result(students);
//使用Gson把result对象转换json字符串
Gson gson = new Gson();
String json = gson.toJson(result);
//输出json字符串到前端
resp.getWriter().write(json);
}
/**
* 获取学生数据集合
*
* @return
*/
private List<Student> getStudents() {
List<Student> students = new ArrayList<>();
students.add(new Student(1L,"李四",20,"mm@163.com"));
students.add(new Student(2L,"王五",21,"mm@163.com"));
students.add(new Student(3L,"赵六",22,"mm@163.com"));
students.add(new Student(4L,"钱七",23,"mm@163.com"));
students.add(new Student(5L,"贵八",24,"mm@163.com"));
return students;
}
}
public class Result {
List<Student> students;
public Result() {
}
public Result(List<Student> students) {
this.students = students;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
public class Student {
private Long id;
private String name;
private Integer age;
private String email;
public Student() {
}
public Student(Long id, String name, Integer age, String email) {
this.id = id;
this.name = name;
this.age = age;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
ult(List students) {
this.students = students;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
```java
public class Student {
private Long id;
private String name;
private Integer age;
private String email;
public Student() {
}
public Student(Long id, String name, Integer age, String email) {
this.id = id;
this.name = name;
this.age = age;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}