vue.js默认没有提供ajax功能的。javascript
因此使用vue的时候,通常都会使用axios的插件来实现ajax与后端服务器的数据交互。css
注意,axios本质上就是javascript的ajax封装,因此会被同源策略限制。html
前端
https://unpkg.com/axios@0.18.0/dist/axios.js
https://unpkg.com/axios@0.18.0/dist/axios.min.js
axios提供发送请求的经常使用方法有两个:axios.get() 和 axios.post() 。vue
增 postjava
删 deletenode
改 putpython
查 getjquery
// 发送get请求
// 参数1: 必填,字符串,请求的数据接口的url地址,例如请求地址:http://www.baidu.com?id=200
// 参数2:可选,json对象,要提供给数据接口的参数
// 参数3:可选,json对象,请求头信息
axios.get('服务器的资源地址',{ // http://www.baidu.com
params:{
参数名:'参数值', // id: 200,
}
}).then(function (response) { // 请求成功之后的回调函数
console.log("请求成功");
console.log(response);
}).catch(function (error) { // 请求失败之后的回调函数
console.log("请求失败");
console.log(error.response);
});
// 发送post请求,参数和使用和axios.get()同样。
// 参数1: 必填,字符串,请求的数据接口的url地址
// 参数2:必填,json对象,要提供给数据接口的参数,若是没有参数,则必须使用{}
// 参数3:可选,json对象,请求头信息
axios.post('服务器的资源地址',{
username: 'xiaoming',
password: '123456'
},{
responseData:"json",
})
.then(function (response) { // 请求成功之后的回调函数
console.log(response);
})
.catch(function (error) { // 请求失败之后的回调函数
console.log(error);
});
// json数据的对象格式:
{
"name":"tom",
"age":18
}
// json数据的数组格式:
["tom",18,"programmer"]
复杂的json格式数据能够包含对象和数组的写法。
{
"name":"小明",
"age":200,
"fav":["code","eat","swim","read"],
"son":{
"name":"小小明",
"age":100,
"lve":["code","eat"],
}
}
方法 | 参数 | 返回值 | 描述 |
---|---|---|---|
stringify | json对象 | 字符串 | json对象转成字符串 |
parse | 字符串 | json对象 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> // json语法 let humen = { "username":"xiaohui", "password":"1234567", "age":20 }; console.log(humen); console.log(typeof humen); // JSON对象提供对json格式数据的转换功能 // stringify(json对象) # 用于把json转换成字符串 let result = JSON.stringify(humen); console.log(result); console.log(typeof result); // parse(字符串类型的json数据) # 用于把字符串转成json对象 let json_str = '{"password":"1123","age":20,"name":"xiaobai"}'; console.log(json_str) console.log(typeof json_str) let json_obj = JSON.parse(json_str); console.log(json_obj); console.log(typeof json_obj) console.log(json_obj.age) </script> </body> </html>
ajax,通常中文称之为:"阿贾克斯",是英文 “Async Javascript And Xml”的简写,译做:异步js和xml数据传输数据。webpack
因此开发中ajax是很经常使用的技术,主要用于操做后端提供的数据接口,从而实现网站的先后端分离。
ajax技术的原理是实例化js的XMLHttpRequest对象,使用此对象提供的内置方法就能够与后端进行数据通讯。
数据接口,也叫api接口,表示
客户端经过发起请求向服务端提供的url地址申请操做数据【操做通常:增删查改】
同时在工做中,大部分数据接口都不是手写,而是经过函数库/框架来生成。
编写代码获取接口提供的数据:
JQ版 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/jquery-1.12.4.js"></script> <script> $(function(){ $("#btn").on("click",function(){ $.ajax({ // 后端程序的url地址 url: 'http://wthrcdn.etouch.cn/weather_mini', // 也可使用method,提交数据的方式,默认是'GET',经常使用的还有'POST' type: 'get', dataType: 'json', // 返回的数据格式,经常使用的有是'json','html',"jsonp" data:{ // 设置发送给服务器的数据,若是是get请求,也能够写在url地址的?后面 "city":'北京' } }) .done(function(resp) { // 请求成功之后的操做 console.log(resp); }) .fail(function(error) { // 请求失败之后的操做 console.log(error); }); }); }) </script> </head> <body> <button id="btn">点击获取数据</button> </body> </html>
总结:
1. 发送ajax请求,要经过$.ajax(),参数是对象,里面有固定的参数名称。
$.ajax({
"url":"数据接口url地址",
"method":"http请求方式,前端只支持get和post",
"dataType":"设置服务器返回的数据格式,经常使用的json,html,jsonp,默认值就是json",
// 要发送给后端的数据参数,post时,数据必须写在data,get能够写在data,也能够跟在地址栏?号后面
"data":{
"数据名称":"数据值",
}
}).then(function(resp){ // ajax请求数据成功时会自动调用then方法的匿名函数
console.log( resp ); // 服务端返回的数据
}).fail(function(error){ // ajax请求数据失败时会自动调用fail方法的匿名函数
console.log( error );
});
2. ajax的使用每每配合事件/钩子操做进行调用。
tml |
是否同源 | 缘由 |
---|---|---|
http://www.oldboy.cn/user/login.html | 是 | 协议、域名、端口相同 |
http://www.oldboy.cn/about.html | 是 | 协议、域名、端口相同 |
https://www.oldboy.cn/user/login.html | 否 | 协议不一样 ( https和http ) |
http:/www.oldboy.cn:5000/user/login.html | 否 | 端口 不一样( 5000和80) |
http://bbs.oldboy.cn/user/login.html | 否 |
同源策略针对ajax的拦截,代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <script src="js/axios.js"></script> </head> <body> <div id="app"> <button @click="get_music">点击获取天气</button> </div> <script> let vm = new Vue({ el:"#app", data:{}, methods:{ get_music(){ axios.get("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=个人中国心") .then(response=>{ console.log(response); }).catch(error=>{ console.log(error.response) }); } } }) </script> </body> </html>
Access to XMLHttpRequest at 'http://tingapi.ting.baidu.com/v1/restserver/ting?
method=baidu.ting.search.catalogSug&query=%E6%88%91%E7%9A%84%E4%B8%AD%E5%9B%BD%E5%BF%83' from origin
'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is
present on the requested resource.
上面错误,关键词:Access-Control-Allow-Origin
只要出现这个关键词,就是访问受限。出现同源策略的拦截问题。
4.2.5 ajax跨域(跨源)方案之CORS
CORS是一个W3C标准,全称是"跨域资源共享",它容许浏览器向跨源的后端服务器发出ajax请求,从而克服了AJAX只能同源使用的限制。
django的视图
def post(request):
response = new Response()
response .set_header("Access-Control-Allow-Origin","*")
// 在响应行信息里面设置如下内容:
Access-Control-Allow-Origin: ajax所在的域名地址
Access-Control-Allow-Origin: www.oldboy.cn # 表示只容许www.oldboy.cn域名的客户端的ajax跨域访问
// * 表示任意源,表示容许任意源下的客户端的ajax均可以访问当前服务端信息
Access-Control-Allow-Origin: *
同源策略:浏览器的一种保护用户数据的一种安全机制。
浏览器会限制脚本语法不能跨源访问其余源的数据地址。
同源:判断两个通讯的地址之间,是否协议,域名[IP],端口一致。
ajax: http://127.0.0.1/index.html
api数据接口: http://localhost/index
这两个是同源么?不是同源的。是否同源的判断依据不会根据电脑来判断,而是经过协议、域名、端口的字符串是否来判断。
1. ajax默认状况下会受到同源策略的影响,一旦受到影响会报错误以下:
No 'Access-Control-Allow-Origin' header is present on the requested resource
2. 解决ajax只能同源访问数据接口的方式:
1. 在服务端的响应行中设置:
Access-Control-Allow-Origin: 容许访问的域名地址
2. jsonp
3. 是否服务端代理
思路:经过python来请求对应的服务器接口,获取到数据之后,
组件(Component)是自定义封装的功能。在前端开发过程当中,常常出现多个网页的功能是重复的,并且不少不一样的网站之间,也存在一样的功能。
而在网页中实现一个功能,须要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,所以就产生了把一个功能相关的[HTML、css和javascript]代码封装在一块儿组成一个总体的代码块封装模式,咱们称之为“组件”。
因此,组件就是一个html网页中的功能,通常就是一个标签,标签中有本身的html内容结构,css样式和js特效。
这样,前端人员就能够在开发时,只须要书写一次代码,随处引入便可使用。
组件有两种:默认组件[全局组件] 和 单文件组件
默认组件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <style> .header{ width: 100%; height: 40px; } .header ul{ list-style:none; padding:0; margin: 0; overflow: hidden; } .header ul li{ width: 120px; height: 40px; line-height: 40px; text-align: center; color: #fff; background-color: blue; float: left; margin-right: 10px; } </style> </head> <body> <div id="app"> <!-- 头部 --> <Tou></Tou> //引用Tou标签 <!-- 脚部--> </div> <script> // Vue.component("组件名称",组件的相关参数[html,css,js代码]); Vue.component("Tou",{ //定义一个Tou标签 template:`<div class="header"> <ul> <li @click="indexHander">{{index}}</li> <li>{{list}}</li> </ul> </div>`, data:function(){ return { index: "首页", list:"列表页" } }, methods:{ indexHander(){ alert("跳转到首页"); } } }); let vm = new Vue({ el:"#app", data:{} }) </script> </body> </html>
// 生成一个基于 webpack 模板的新项目
vue init webpack myproject
// 启动开发服务器 ctrl+c 中止服务
cd myproject npm run dev # 运行这个命令就能够启动node提供的测试http服务器
├── build/ ├── config/ ├── index.html ├── node_modules/ # 项目运行的依赖库存储目录[很是大] ├── package.json # 项目运行须要的依赖库记录配置 ├── src/ │ ├── App.vue # 父级组件 │ ├── assets/ # 静态资源目录,图片存放在这里 │ ├── components/ # 单文件组件保存目录 │ └── main.js └── static/ # 静态资源目录,全部的css,js等文件放在这个目录
src 主开发目录,要开发的单文件组件所有在这个目录下的components目录下
static 静态资源目录,全部的css,js文件放在这个文件夹
dist 项目打包发布文件夹,最后要上线单文件项目文件都在这个文件夹中[后面打包项目,让项目中的vue组件通过编译变成js 代码之后,dist就出现了]
config是配置目录,
build是项目打包时依赖的目录
src/router 路由,后面须要咱们在使用Router路由的时候,本身声明.
普通组件的缺点:
html代码是做为js的字符串进行编写,因此组装和开发的时候不易理解,并且没有高亮效果。
普通组件用在小项目中很是合适,可是复杂的大项目中,若是把更多的组件放在html文件中,那么维护成本就会变得很是昂贵。
普通组件只是整合了js和html,可是css代码被剥离出去了。使用的时候的时候很差处理。
将一个组件相关的html结构,css样式,以及交互的JavaScript代码从html文件中剥离出来,合成一个文件,这种文件就是单文件组件,至关于一个组件具备告终构、表现和行为的完整功能,方便组件之间随意组合以及组件的重用,这种文件的扩展名为“.vue”,好比:"Home.vue"。
<template> </template> <script> </script> <style> </style>
<template> <div id="Home"> # 全部代码要在一个块里面 <Header/> <div class="main"> 页面主题内容 </div> <div class="footer"> 页面脚步内容 </div> </div> </template> 下面写法会报错 <template> <Header/> <div class="main"> 页面主题内容 </div> <div class="footer"> 页面脚步内容 </div> </template>
<script> import Header from "./common/Header" export default { name:"Home", // 组件名称,用于之后路由跳转 data(){ // 当前组件中须要使用的数据 return { } }, components:{ Header, } } </script>
// scoped 表示当前style的样式只做用于当前组件的template代码中,其余地方不会被影响 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
home组件引入header组件 (和app中引入Home相似)
<template> <div id="Home"> <Header/> <div class="main"> <p>加减数字的功能</p> <div class="box"> <button @click="num++">+</button> <input type="text" v-model="num"> <button @click="num--">-</button> </div> </div> <div class="footer"> 页面脚步内容 </div> </div> </template> <script> import Header from "./common/Header" export default { name:"Home", // 组件名称,用于之后路由跳转 data(){ // 当前组件中须要使用的数据 return { num:0, // 这里须要声明num } }, components:{ Header, } } </script> // scoped 表示当前style的样式只做用于当前组件的template代码中,其余地方不会被影响 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
<template> <div id="menu"> <span>{{msg}}</span> <p>我是menu视图,我是主题body部分</p> </div> </template> <script> export default { name:"Menu", // 组件名称,用于之后路由跳转 data(){ // 当前组件中须要使用的数据 return { msg: "你们好" } } } </script> // scoped 表示当前style的样式只做用于当前组件的template代码中,其余地方不会被影响 <style scoped> </style>
而后,在父组件 Home.vue 中调用上面声明的子组件。
// Menu 首字母大写 <template> <div> <Header /> <div class="main"> <p>增减数字</p> <button @click="num++">+</button> <input type="text" name="" id="" v-model="num"> <button @click="num--">-</button> </div> <Menu /> //调用 </div> </template> <script> import Header from "./common/Header" import Menu from "./common/Menu" //导入 export default{ name: "Home", data(){ return{ num:0, } }, components:{ Header,Menu //声明 } } </script> <style> </style>
能够经过props属性来进行传递.
在父组件中,调用子组件的组名处,使用属性值的方式往下传递数
<template>
<Menu :mynum="num" title="home里面写的数据"/>
</template>
# 上面表示在父组件调用Menu子组件的时候传递了2个数据:
若是要传递变量[变量能够各类类型的数据],属性名左边必须加上冒号:,同时,属性名是自定义的,会在子组件中使用。
若是要传递普通字符串数据,则不须要加上冒号:
<script> export default { name:"Menu", props:["mynum","title"], //用props接收值 data: function(){ return { msg:"这是Menu组件里面的菜单", } } } </script>
在子组件中的template中使用父组件传递过来的数据.
<template> <div id="menu"> <span>{{msg}},{{title}}</span> <div>hello,{{mynum}}</div> </div> </template>
传递数据是变量,则须要在属性左边添加冒号.
传递数据是变量,这种数据称之为"动态数据传递"
传递数据不是变量,而是数值或者字符串,这种数据称之为"静态数据传递"
父组件中修改了数据,在子组件中会被同步修改,可是,子组件中的数据修改了,是不会影响到父组件中的数据.
这种状况,在开发时,也被称为"单向数据流"
事实上,咱们若是要在子组件中把数据传递给父组件,也能够完成的。
经过事件冒泡的方式,进行数据传递
在vue中提供的this.$emit()方法进行给咱们传递数据
默认状况下,咱们的项目中并无对axios包的支持,因此咱们须要下载安装。
在项目根目录中使用 npm安装包在命令行下执行安装包的命令:
npm install axios
接着在main.js文件中,导入axios并把axios对象 挂载到vue属性中多为一个子对象,这样咱们才能在组件中使用。
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' // 这里表示从别的目录下导入 单文件组件 import axios from 'axios'; // 从node_modules目录中导入包 Vue.config.productionTip = false Vue.prototype.$http = axios; // 把对象挂载vue中 $http 能够本身定义名称 /* eslint-disable no-new */ new Vue({ el: '#app', components: { App }, template: '<App/>' });
代码编写在Heaer.vue子组件中
<template> <div id="Header" class="header"> {{message}} <p>num: <input type="text" v-model="num"></p> <p>深圳的天气状况: {{weather_info}}</p> </div> </template> <script> export default { name:"Header", // 组件名称,用于之后路由跳转 props:["num"], data(){ // 当前组件中须要使用的数据 return { message:"页面头部", weather_info:"", } }, // 钩子方法,在页面中vue挂在data数据之后,自动执行 created() { // 使用axios发送请求获取数据 this.$http.get("http://wthrcdn.etouch.cn/weather_mini?city=深圳").then(response=>{ console.log(response.data); console.log(response.data.data.ganmao); this.weather_info = response.data.data.ganmao; }).catch(error=>{ }); } } </script> // scoped 表示当前style的样式只做用于当前组件的template代码中,其余地方不会被影响 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
使用的时候,由于本质上来讲,咱们仍是原来的axios,因此也会收到同源策略的影响。
后面开发项目的时候,咱们会使用cors来解决跨域的问题