Vue(day3)
一、Vue中的ajax:vue-resource和axios
vue-resource
是Vue实现异步加载的官方库,即Vue中的ajax。在Vue2.js之后vue-resource
将不再更新维护,所以推荐尽量使用第三方库axios
实现异步加载。
下面将对两种库分别进行使用说明,参考:
1、vue-resource的使用
首先我们需要引入库文件:
<script src="https://cdn.jsdelivr.net/npm/vue-resource@1.5.1"></script>
vue-resource
同jquery
封装的Ajax一样,提供了简易的api实现异步访问。提供了 7 种请求 API(REST 风格):
get(url, [options])
head(url, [options])
delete(url, [options])
jsonp(url, [options])
post(url, [body], [options])
put(url, [body], [options])
patch(url, [body], [options])
除了 jsonp 以外,另外 6 种的 API 名称是标准的 HTTP 方法。
具体的参数说明请参考:Vue.js-菜鸟
在Vue中,你可以基于全局或组建进行异步访问:
// 基于全局Vue对象使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
// 在一个Vue实例内使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
下面我们使用具体的案例来体验一下。
2、vue-resoure案例:获取商品列表
我们现在的需求是,使用vue-resource
提供的api获取服务端发送来的数据,并显示出来。然后可以添加和删除页面上的商品数据,并发送请求更新服务端的数据。
分析
- 首先我们需要从服务端获取商品信息,所以我们需要自己模拟一个服务端,使用Node.js来快速搭建即可。
- 异步加载可能出现跨域的问题,我们可以使用api提供的
jsonp
方法进行数据的访问,也可以将页面放到在Node服务器上访问,这里我们使用第二种方法。
准备工作
使用node搭建服务器
首先我们需要安装第三方模块:express、body-parser。
npm install express body-parser
书写app.js文件:
//加载需要的模块
var express = require('express');
var app = express();
var fs = require('fs');
var path = require('path');
var bodyParser = require('body-parser'); //启动服务器
app.listen(8080, function(){
console.log('server running at 8080');
}); //相关配置
app.use('/views', express.static(path.join(__dirname, './views')));//静态资源
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false })); //相关请求
app.get('/', (req, res) => {
res.redirect(302, '/views/index.html');
});
页面文件index.html
我们把这个文件放在node文件夹的views下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>添加信息</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-resource@1.5.1"></script> </head>
<body>
<div id="app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">{{title}}</h3>
</div>
</div>
<div class="panel-body form-inline">
<label>
Id:
<input type="text" v-model="id" class="form-control" required="true" @keyup.enter="add">
</label>
<label>
Name:
<input type="text" v-model="name" class="form-control" required="true" @keyup.enter="add">
</label>
<input type="button" class="btn btn-primary" @click="add" value="添加">
<label style="color: red;cursor: pointer;" @click="clearMessage"> {{message}} </label>
</div>
<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
<td>Id</td>
<td>Name</td>
<td>Date</td>
<td>Control</td>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td><span title="删除" @click="deleteItem(item.id)" style="cursor: pointer;color: red;" class="glyphicon glyphicon-remove"></span></td>
</tr>
</tbody>
</table>
</div> <script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
list : [],
id:'',
name:'',
title: '添加信息',
message: ''
},
methods: {
add(){
console.log("添加");
},
clearMessage(){
this.message = '';
},
deleteItem(id){
console.log("删除");
}
}
});
</script>
</body>
</html>
启动服务器查看效果
获取信息列表
Node.js返回数据
我们使用
list.json
这个文件来充当数据库。app.get('/getlist', (req, res) => {
fs.readFile('./list.json', 'utf8', (err, data) => {
if(err){
res.json(err);
}else{
res.json(JSON.parse(data.toString()));
}
});
});
{
"list":[
{"id":"1","name":"宝马","date":"2019/2/18"},
{"id":"2","name":"众泰","date":"2019/2/18"},
{"id":"3","name":"梅赛德斯","date":"2019/2/19"},
{"id":"4","name":"奥迪","date":"2019/2/19"}
]
}
使用get请求获取信息
getList(){
this.$http.get('http://localhost:8080/getlist').then((res) => {
if(!res.body){
this.message = '信息获取失败'
}else{
this.list = res.body.list;
}
});
}
这个方法目前没有被调用,我们希望在页面加载时渲染到页面,根据Vue的生命周期,我们可以使用钩子函数
created
来调用:created(){
this.getList();
},
完整的文件最后会给出。
显示效果
添加信息
信息的添加功能为add
函数,同样的,我们需要发送post请求(其他方式也可),将新的数据更新到list.json文件中。
页面提交post请求
add(){
if(this.id.trim() == '' || this.name.trim() == ''){
this.message = "输入不能为空";
return;
}
//1、读取表单信息,将信息存制list
for(var i = 0;i < this.list.length;i++){
if(this.list[i].id === this.id){
this.message = "id不能重复";
return;
}
}
this.list.push({"id": this.id, "name":this.name, "date": new Date().toLocaleDateString()});
//2、将新的list更新到json文件中
this.setList();
}
setList(){
var listObj = {
list: this.list
};
this.$http.post('http://localhost:8080/setlist', {list: listObj}).then(function(result){
if(result && +result.status === 200){
this.message = "更新成功";
}else{
this.message = "更新失败";
this.getList();
}
});
}
服务器接收post请求
app.post('/setlist', function(req, res){
var dataStr = JSON.stringify(req.body.list);
fs.writeFile('./list.json', dataStr, 'utf8', function(err){
if(err){
res.json({status: 200, message: 'ok'});
}else{
res.json({status: 500, message: 'failed'});
}
});
});
删除信息
删除和添加时一样的逻辑。
页面发送请求
deleteItem(id){
for(var i = 0;i < this.list.length;i++){
if(id === this.list[i].id){
this.list.splice(i, 1);
i = this.list.length;
}
}
this.setList();
}
一些全局配置
Vue.http.options.root = '/root';//域名
Vue.http.headers.common['Authorization'] = 'Basic YXBpOnBhc3N3b3Jk';
Vue.http.options.emulateJSON = true;//服务器无法编码时使用
//如果您的Web服务器无法处理PUT,PATCH和DELETE等REST / HTTP请求,则可以启用emulateHTTP选项。 这将使用实际的HTTP方法设置X-HTTP-Method-Override标头并使用普通的POST请求。
Vue.http.options.emulateHTTP = true;
完整文件
app.js
//加载需要的模块
var express = require('express');
var app = express();
var fs = require('fs');
var path = require('path');
var bodyParser = require('body-parser'); //启动服务器
app.listen(8080, function(){
console.log('server running at 8080');
}); //相关配置
app.use('/views', express.static(path.join(__dirname, './views')));//配置静态资源
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false })); //相关请求
app.get('/', (req, res) => {
res.redirect(302, '/views/index.html');
});
app.get('/getlist', (req, res) => {
fs.readFile('./list.json', 'utf8', (err, data) => {
if(err){
res.json(err);
}else{
res.json(JSON.parse(data.toString()));
}
});
});
app.post('/setlist', function(req, res){
var dataStr = JSON.stringify(req.body.list);
fs.writeFile('./list.json', dataStr, 'utf8', function(err){
if(err){
res.json({status: 200, message: 'ok'});
}else{
res.json({status: 500, message: 'failed'});
}
});
});
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>添加信息</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-resource@1.5.1"></script> </head>
<body>
<div id="app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">{{title}}</h3>
</div>
</div>
<div class="panel-body form-inline">
<label>
Id:
<input type="text" v-model="id" class="form-control" required="true" @keyup.enter="add">
</label>
<label>
Name:
<input type="text" v-model="name" class="form-control" required="true" @keyup.enter="add">
</label>
<input type="button" class="btn btn-primary" @click="add" value="添加">
<label style="color: red;cursor: pointer;" @click="clearMessage"> {{message}} </label>
</div>
<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
<td>Id</td>
<td>Name</td>
<td>Date</td>
<td>Control</td>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td><span title="删除" @click="deleteItem(item.id)" style="cursor: pointer;color: red;" class="glyphicon glyphicon-remove"></span></td>
</tr>
</tbody>
</table>
</div> <script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
list : [],
id:'',
name:'',
title: '添加信息',
message: ''
},
created(){
this.getList();
},
methods: {
add(){
if(this.id.trim() == '' || this.name.trim() == ''){
this.message = "输入不能为空";
return;
}
//1、读取表单信息,将信息存制list
for(var i = 0;i < this.list.length;i++){
if(this.list[i].id === this.id){
this.message = "id不能重复";
return;
}
}
this.list.push({"id": this.id, "name":this.name, "date": new Date().toLocaleDateString()});
//2、将新的list更新到json文件中
this.setList();
},
setList(){
var listObj = {
list: this.list
};
this.$http.post('http://localhost:8080/setlist', {list: listObj}).then(function(result){
if(result && +result.status === 200){
this.message = "更新成功";
}else{
this.message = "更新失败";
this.getList();
}
});
},
clearMessage(){
this.message = '';
},
deleteItem(id){
for(var i = 0;i < this.list.length;i++){
if(id === this.list[i].id){
this.list.splice(i, 1);
i = this.list.length;
}
}
this.setList();
},
getList(){
this.$http.get('http://localhost:8080/getlist').then((res) => {
if(!res.body){
this.message = '信息获取失败'
}else{
this.list = res.body.list;
}
});
}
}
});
</script>
</body>
</html>
3、axios的使用
axios
的使用同vue-resource
基本一致。我们使用axios
重写上面获取信息列表的方法就一目了然了:
导入库文件
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
重写getList
getList(){
axios.get('http://localhost:8080/getlist').then((res) => {
if(!res.data){
this.message = '信息获取失败'
}else{
this.list = res.data.list;
}
});
}
可以发现,this.$http.get() 变成了 axios.get(),而response返回的数据存在data中而不是body中。
更多细节请参考:axios
二、过滤和动画
1、css3过渡和动画简介
过渡
看下面的例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
div{
width: 100px;
height: 100px;
background-color: #999111;
}
div:hover{
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
当我们的鼠标悬浮在div
元素上时,元素的样式发生了变化,但是这是瞬时变化的,在CSS3加入过渡和动画之前,元素属性(样式)变化都是没有时间轴的。
为了提高用户体验,CSS3实现了元素的过渡和动画效果。在上面的例子中,我们使用为元素加上过渡属性:transition
。
div{
width: 100px;
height: 100px;
background-color: #999111;
transition: all 1s ease;
}
这样,我们就能看到元素在样式变化过程中的过渡效果。
关于transition
的更多用法请自行查阅。
动画
对于过渡来说,我们需要事件触发才能看到效果,即存在状态变化,且过渡只在元素的两个状态之间变化。很多时候我们不需要事件触发也能实现状态变化,且能控制变化状态。这就是更复杂的动画功能,使用animation
属性。
动画比过渡多了状态控制的过程,所以css动画需要结合keyframes(关键帧)
来结合animation
属性使用。
更多相关属性可自行查阅学习。
这里有一个css动画案例:行星运动
参考:
http://www.runoob.com/css3/css3-animations.html
http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html
2、Vue中的过滤和动画
详情请参考官方文档:https://cn.vuejs.org/v2/guide/transitions.html
概述
在Vue中,可以在插入、更新或移除DOM时提供不同方式的过渡效果:
- 使用class类
- 配合使用第三方css动画插件,如
Animated.css
- 使用js
- 配合使用第三方js动画插件,如
Velocity.js
这些本质上都是CSS过渡和动画的封装实现,只是可以让我们使用更少的代码实现更多的功能(需求)。
过渡的类
Vue把过渡分为两个阶段来实现过渡效果,分别是进入阶段、离开阶段。而这两个阶段又再细分为前和后两个阶段,具体如图所示:
下面是一个简单的例子:
由于Vue能在适当的时机添加类,所以不需要我们手动绑定类名,但是我们需要使用Vue提供的Transition
组件来包裹需要过渡的元素。
<div id="app">
<button @click="show = !show">Toggle</button>
<transition>
<h3 v-show="show">This is a message.</h3>
</transition>
</div>
.v-enter-active, .v-leave-active{
transition: all 0.8s ease;
}
.v-enter, .v-leave-to{
transform: translateX(10px);
opacity: 0;
}
var app = new Vue({
el: '#app',
data: {
show: true,
}
});
transition
的name属性可以自定义类名的前缀,如name="my-transition"
,那么类名就变成my-transition-enter
等。
自定义过渡的类名:使用第三方css库
Vue提供了自定义过渡类名的特性:
- enter-class
- enter-active-class
- enter-active-to(2.1.8+)
- leave-class
- leave-active-class
- leave-to-class(2.1.8+)
这样我们就可以使用自定义的类名来定义不同的过渡效果,下面我们结合第三方css库来使用:
<button @click="show = !show">Toggle</button>
<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
<h3 v-show="show">This is a message.</h3>
</transition>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
我们使用了Animation.css
提供的类样式:animated、bounceIn和bounceOut。只需要放在适合的类中即可自动加载触发。
Vue动画
CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter
类名在节点插入 DOM 后不会立即删除,而是在 animationend
事件触发时删除。
js钩子
上面我们可以通过类名来控制过渡效果,下面我们还可以使用js钩子函数来控制:
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
还有很多的Vue动画特性,这样不再赘述,可自行到官网查阅学习。
三、组件
组件名
给一个组件注册一个符合其用途的名称是我们应当考虑的,且尽量遵循W3C规范,即名称全小写,必要的单词以以字符分隔开。例如:
Vue.component('show-number', {/*...*/});
Prop
1、prop的命名
在html中特性名称prop是大小写不敏感的,浏览器会将大写当做小写来处理,所以驼峰式(camelCase)的写法可以换成连字符的写法(kebab-case)。
2、props的类型
有两种写法:
字符串数组形式:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
对象形式:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object
}
推荐使用对象形式,因为这种不但清晰地标明了数据类型,还能在js报错的时候发出相应的信息提示。
3、静态赋值和动态赋值
所谓的静态赋值就是将一个不变的数据传给prop,而动态赋值就是将一个变量传给prop,以此来达到动态赋值的效果。
静态
<my-component titile="Boom"></my-component>
动态
<my-component :title="data.title"></my-component>
<my-component :title="'this is' + data.title"></my-component>
虽然我们都是在传递一个字符串,但理论是支持任意类型的数据。需要注意的是,如果我们希望传递一个数字就不能单纯的使用静态赋值,因为这样会变被当成字符串来处理。同样的道理,对于Boolean值、数组、对象,我们都需要使用动态赋值来保证数据的类型。
一次性赋值
如果你希望将所有的prop作为整个对象传入,可以使用不带名称的
v-bind
进行赋值。例如:假定有一个对象props = {
id: 1,
title: 'hiahia'
}
一次性赋值:
<my-component v-bind="props"></my-component>
等价于:
<my-component :id="props.id" :title="props.title"></my-component>
4、单向流数据
所有的prop都使得其父子之间的prop形成一个单向下行绑定:父级更新将会更新子组件的prop,但反过来却不行,所以Vue不允许在子组件中出现修改prop的情况。
5、prop验证
上面提到的推荐的prop类型是对象类型,我们可以对组件进行验证性信息传入,当不符合注册规则是发出错误信息。如:
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
6、禁用特性继承
如果你不希望组件的根元素继承特性,那么你可以在注册是加上这个特性:inheritAttrs: false
。
Vue(day3)的更多相关文章
- vue day3 bootstrap 联动下拉
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta ht ...
- Vue.js - Day3
定义Vue组件 什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可: 组件化和模块化的不同: ...
- day3(Vue组件)
1.组件定义 1.定义组件并引用 2.父组件向子组件传值 3.子组件向父组件传值 # 组件间传值:vuex (https://www.cnblogs.com/xiaonq/p/9697921.html ...
- vue学习笔记3
Vue.js - Day3 定义Vue组件 什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即 ...
- vue(9)—— 组件化开发 - webpack(3)
前面两个终于把webpack相关配置解析完了.现在终于进入vue的开发了 vue组件化开发预热 前期准备 创建如下项目: app.js: footer.js: main.js: webpack.con ...
- Vue入门到精通
Vue.js - Day1 课程介绍 前5天: 都在学习Vue基本的语法和概念:打包工具 Webpack , Gulp 后5天: 以项目驱动教学: 什么是Vue.js Vue.js 是目前最火的一个前 ...
- Vue.js 和 MVVM 小细节
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
随机推荐
- unwrapThrowable
package org.apache.ibatis.reflection; import java.lang.reflect.InvocationTargetException; import jav ...
- 从JVM内存管理的角度谈谈JAVA类的静态方法和静态属性
在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题. 一般,JVM的 ...
- Embedded servlet containers
73. Embedded servlet containers 73.1 Add a Servlet, Filter or Listener to an application There are t ...
- 区分IE8 、IE9 、IE10的专属css hack
想让IE8及以下的浏览器实现同样的效果,且不希望使用css3pie或htc或条件注释等方法时,可能就会需要用到IE8和IE9的专属css hack了. .test{ /* 1. */ color:#0 ...
- Python软件目录结构规范
设计项目目录结构和'代码编码风格'一样, 是为了达到以下两点: 可读性高 可维护性高 目录组织方式 Stackoverflow上有一些比较好的范式.
- 【bzoj 1407】【Noi2002】Savage
Description Input 第1行为一个整数N(1<=N<=15),即野人的数目. 第2行到第N+1每行为三个整数Ci, Pi, Li表示每个野人所住的初始洞穴编号,每年走过的洞穴 ...
- 【强连通分量】Bzoj1654 [Usaco2006 Jan]The Cow Prom 奶牛舞会
Description 约翰的N(2≤N≤10000)只奶牛非常兴奋,因为这是舞会之夜!她们穿上礼服和新鞋子,别上鲜花,她们要表演圆舞. 只有奶牛才能表演这种圆舞.圆舞需要一些绳索和一个圆形的 ...
- BZOJ_5301_[Cqoi2018]异或序列&&CF617E_莫队
Description 已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l.r ,问在 [l,r] 区间内,有多少连续子 序列满足异或和等于 k . 也就是说,对于所 ...
- Feature Preprocessing on Kaggle
刚入手data science, 想着自己玩一玩kaggle,玩了新手Titanic和House Price的 项目, 觉得基本的baseline还是可以写出来,但是具体到一些细节,以至于到能拿到的出 ...
- dubbo+zookeeper的使用
我们讨论过Nginx+tomcat组成的集群,这已经是非常灵活的集群技术,但是当我们的系统遇到更大的瓶颈,全部应用的单点服务器已经不能满足我们的需求,这时,我们要考虑另外一种,我们熟悉的内容,就是分布 ...