vue_基础(2)
目录:
axios
vue-axios
vue.js默认没有提供ajax功能的。
所以使用vue的时候,一般都会使用axios的插件来实现ajax与后端服务器的数据交互。
注意,axios本质上就是javascript的ajax封装,所以会被同源策略限制。
下载地址:
https://unpkg.com/axios@0.18.0/dist/axios.js
https://unpkg.com/axios@0.18.0/dist/axios.min.js
通过axios实现数据请求
axios提供发送请求的常用方法有两个:axios.get() 和 axios.post() 。
增 post
删 delete
查 get
// 发送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); }); // b'firstName=Fred&lastName=Flintstone'
数据接口
数据接口,也叫api接口,表示后端提供
操作数据/功能的url地址给客户端使用。
客户端通过发起请求向服务端提供的url地址申请操作数据【操作一般:增删查改】
同时在工作中,大部分数据接口都不是手写,而是通过函数库/框架来生成。
ajax和axios的对比使用
获取天气信息
编写代码获取接口提供的数据
axios获取天气
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> 请输入您想查询城市:<input type="text" v-model="city"> <button @click="get_weather">确定</button> <h2 style='color: red'>{{message}}</h2> </div> </body> <script src="vue.js"></script> <script src="axios.js"></script> <script> new Vue({ el: '#app', data() { return { city:'', message:'', // 展示查询到的信息 } }, methods:{ get_weather(){ axios.get('http://wthrcdn.etouch.cn/weather_mini?',{ params:{ city:this.city, } }) .then((res)=>{ console.log(res) this.message = res.data.data.city + ':' + res.data.data.ganmao; }).catch(function (error){ console.log(error) }) } } }) </script> </html>
ajax获取天气
ajax的使用必须与服务端程序配合使用,但是目前我们先学习ajax的使用,所以暂时先不涉及到服务端python代码的编写。因此,我们可以使用别人写好的数据接口进行调用。
jQuery将ajax封装成了一个函数$.ajax(),我们可以直接用这个函数来执行ajax请求。
<!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) { // 请求成功以后的操作,新的ajax是这样写的,之前是通过属性success:function(){}的形式来写的 console.log(resp); }) .fail(function(error) { // 请求失败以后的操作 error:function(){} 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的使用往往配合事件/钩子操作进行调用。
同源策略
测试:
<!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
CORS是一个W3C标准,全称是"跨域资源共享",它允许浏览器向跨源的后端服务器发出ajax请求,从而克服了AJAX只能同源使用的限制。
实现CORS主要依靠后端服务器中响应数据中设置响应头信息返回的。
首先创建两个django项目, t1, t2 ,
分别分配不同的端口号模拟同源机制: http://127.0.0.1:8001/ http://127.0.0.1:8000/
t1中向t2发送get请求获取数据
# t1
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <button @click="btn">获取数据</button> </div> </body> <script src="{% static 'vue.js' %}"></script> <script src="{% static 'axios.js' %}"></script> <script> new Vue({ el: '#app', data() { return {} }, methods:{ btn(){ axios.get('http://127.0.0.1:8001/data/') // 指定获取数据 .then(function (res){ console.log(res) }).catch(function (error){ console.log(error) }) } } }) </script> </html>
t2中的views
from django.http import JsonResponse def data(request): info = {'name': 'I', 'say': ' love you'} ret = JsonResponse(info) return ret
同样的出现了如下报错
j解决方案,我们只需要在视图中添加Access-Control-Allow-Origin响应键值对即可
def data(request): info = {'name': 'I', 'say': ' love you'} ret = JsonResponse(info) ret['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' # 允许该地址的请求正常获取响应数据 # ret['Access-Control-Allow-Origin'] = '*' # 允许所有地址请求都能拿到数据 return ret
组件化开发
组件 component
而在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个功能相关的[HTML、css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”。
所以,组件就是一个html网页中的功能,一般就是一个标签,标签中有自己的html内容结构,css样式和js特效。
这样,前端人员就可以在开发时,只需要书写一次代码,随处引入即可使用。
我们在进行vue开发的时候,还记得我们自己创建的vm对象吗,这个vm对象我们称为一个大组件,根组件(页面上叫Root),在一个网页的开发中,根据网页上的功能区域我们又可以细分成其他组件,或称为子组件
组件有两种:默认组件[全局组件] 和 单文件组件[局部组件]
局部组件
三步 : 生子 挂子 用子
注意:每个组件中的template对应的标签,都必须有一个外层标签包裹
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <!--3. 使用子组件--> <!--组件化开发, 页面上需要哪些子组件,就将哪些组件拼到页面上显示--> <Vheader></Vheader> <Banner></Banner> </div> </body> <script src="vue.js"></script> <script> // 1. 声明子组件 除了没有el 其他和vue对象一样 let Vheader ={ data(){ return{ nav_list: ['个人中心','登录','注册']} }, template: ` <div> <h1>{{nav_list}}</h1> </div> ` } let Banner = { data(){ return{content: '内容区域,这里有好多小图片,你看不到吧!'} }, template: ` <div> <h1 style="color: red">{{content}}</h1> </div> ` } let vm = new Vue({ el:"#app", data(){ return{ } }, components:{ Vheader:Vheader, // 2.挂载子组件,都挂载到vue中 Banner, // 键和值相同时,可以简写 } }) </script> </html>
全局组件 : 子组件都写在Vue上面
直接看代码,局部组件使用时需要挂载,全局组件使用时不需要挂载。那么他们两个什么时候用呢,局部组件就在某个局部使用的时候,全局组件是大家公用的,或者说每个页面都有这么一个功能的时候,在哪里可能都会用到的时候。
<div id="app"> <love></love> <kk></kk> </div> </body> <script src="vue.js"></script> <script> // 全局组件 不需挂载,直接使用 Vue.component('kk',{ data(){ return{ name:'全局组件!!!' } }, template:` <h1 style="color: yellow">{{name}}</h1> ` }) new Vue({ el:"#app", data(){ return{} } }) </script>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> <!--使用子组件--> </div> </body> <script src="vue.js"></script> <script> let aa = { // 声明aa子组件 data(){ return{hobby:'听歌,跳舞'} }, template:'<h2 style="color: red">{{hobby}}</h2>' } let bb = { // 声明bb子组件 data(){ return{dream:'妹妹, money'} }, template: `<h2 style="color: tan">{{dream}}</h2>` } // 包工头 let App = { data() { return{msg:'我是App'} }, template:` <div class="app"> <h1>{{msg}}</h1> <aa></aa> <bb></bb> </div> `, components:{ aa,bb, // 将那两个小组件挂载到这 } } // Vue对象 let vm = new Vue({ el:'#app', data(){ return{ } }, components:{ App, // 将包工头挂载到这 } }) </script> </html>
注意: components一定要加s , 不要使用data:{ } 了
组件传值
父组件向子组件传值 prop
props是子组件用来接收父组件传递过来的数据的一个自定义属性
父组件的数据需要通过props把数据传给子组件 ,子组件需要显式地用 props 选项声明 "prop":
两步: 1. 父组件在使用子组价的时候要定义自定义的属性,比如: 动态传值: <Vheader :ff="num"></Vheader> 静态传值: <Vheader ff="123"><Vheader> 2. 在子组件中使用props属性声明: 比如 props['ff',],然后子组件就可以将 ff作为一个数据属性来使用了比如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--两步:--> <!-- 1. 父组件在使用子组价的时候要定义自定义的属性,比如:--> <!-- 动态传值: <Vheader :ff="num"></Vheader>--> <!-- 静态传值: <Vheader ff="123"><Vheader>--> <!-- 2. 在子组件中使用props属性声明: 比如 props['ff',],然后子组件就可以将--> <!-- ff作为一个数据属性来使用了比如: --> <div id="app"> <App></App> </div> </body> <script src="vue.js"></script> <script> let Vheader = { data(){ return{} }, template:`<h1>{{ff}}</h1>`, props:['ff',], // 接收父组件的值 } let App = { data(){ return{message: 'App', num:100} }, template:` <div class="app"> <h2>{{message}}</h2> <Vheader :ff="num"></Vheader> //动态传值 </div> // <Vheader ff='123'></Vheader> // 静态传值 `, components:{ Vheader, } } new Vue({ el:'#app', components:{ App, } }) </script> </html>
使用父组件传递数据给子组件时, 注意一下几点:
-
传递数据是变量,则需要在属性左边添加冒号.
传递数据是变量,这种数据称之为"动态数据传递"
传递数据不是变量,这种数据称之为"静态数据传递"
-
父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.
这种情况,在开发时,也被称为"单向数据流"
子组件向父组件传值
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用
$on(eventName)
监听事件 - 使用
$emit(eventName)
触发事件
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
a. 子组件中使用 this.$emit('ffunc',val) // ffunc是父组件中使用子组件的地方添加的绑定自定义事件 this.$emit('ffunc', this.num); b. 父组件中的methods中写一个自定义的事件函数: recv_data(val), 这个val就是子组件传过来的数据 <son @ffunc="recv_data"></son>
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <App></App> </div> </body> <script src="vue.js"></script> <script> let son = { data(){ return{msg:'我是子组件', num:1000, // num传递给父组件 } },template: ` <div> <h2>{{msg}}</h2> <button @click="zouni">点击传值</button> </div> `, methods:{ zouni(){ // 给父组件传值 this.$emit('ffunc', this.num); } } } let App = { data(){ return{ msg:'我是父组件',son_data:''} }, template:` <div> <son @ffunc="recv_data"></son> // 父组件使用子组件的时候,写上一个自定义事件 <h3>{{msg}}</h3> <h3 style="color: #2c3e50">{{son_data}}</h3> </div> ` ,components:{ son, },methods:{ recv_data(val){ this.son_data = val } } } let vm = new Vue({ el:'#app', components:{ App, } }) </script> </html>
平行组件传值
看代码 :声明两个全局组件T1和T2,T1组件将数据传送给T2组件
a. 声明一个公交车, t1组件使用$.emit往公交车上传值
b. t2组件使用 bus.$on 从公交车上获取值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> </body> <script src="vue.js"></script> <script> // 1.声明一个公交车 let bus = new Vue(); Vue.component('t1',{ data(){ return{ msg:'hello', num:200, } },template:` <div class="t1"> <h1>{{msg}}</h1> <button @click="kk">点我</button> </div> `, // 2. 往公交车上放值 methods:{ kk(){ bus.$emit('xxx', this.num) } } }) Vue.component('t2',{ data(){ return{msg:'hello',t1_num:''} },template:` <div> <h1>{{msg}}</h1> <h2>{{t1_num}}</h2> </div> `, created(){ bus.$on('xxx',(val)=>{ this.t1_num = val; }) } }) let App = { data(){ return{msg:'App'} }, template:` <div class="app"> <t1></t1> <t2></t2> </div> ` } new Vue({ el:"#app", components:{ App, } }) </script> </html>
vue-router的使用
vue就是我们前面学习的vue基础,vue + vue-router 主要用来做SPA(Single Page Application),单页面应用
那么解释一下什么是单页应用,看下图:(react、angular也都是做单页面应用,很多大型的网站像网易云音乐,豆瓣等都是react写的单页面应用)
HTML
<script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <!-- 路由出口 --> <!-- 路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div>
JavaScript
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter) // 1. 定义 (路由) 组件。 // 可以从其他文件 import 进来 const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } // 2. 定义路由 // 每个路由应该映射一个组件。 其中"component" 可以是 // 通过 Vue.extend() 创建的组件构造器, // 或者,只是一个组件配置对象。 // 我们晚点再讨论嵌套路由。 const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] // 3. 创建 router 实例,然后传 `routes` 配置 // 你还可以传别的配置参数, 不过先这么简单着吧。 const router = new VueRouter({ routes // (缩写) 相当于 routes: routes }) // 4. 创建和挂载根实例。 // 记得要通过 router 配置参数注入路由, // 从而让整个应用都有路由功能 const app = new Vue({ router }).$mount('#app') // 现在,应用已经启动了!
通过注入路由器,我们可以在任何组件内通过 this.$router
访问路由器,也可以通过 this.$route
访问当前路由:
// Home.vue export default { computed: { username() { // 我们很快就会看到 `params` 是什么 return this.$route.params.username } }, methods: { goBack() { window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/') } } }
使用流程
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> </body> <script src="vue.js"></script> <script src="vue-router.js"></script> <script> // 1. 定义路由组件 let Home = { data(){ return{ msg :'我是home组件', } },template:` <div class="home"> <h1>{{msg}}</h1> </div> ` } let Course = { data(){ return{ msg:'我是course组件', } },template:` <div class="course"> <h1>{{msg}}</h1> </div> ` } // 2. 定义路由, 一个路由对应一个组件 const routes = [ { path: '/home', component:Home}, { path: '/course', component:Course}, ] // 3. 创建 VueRouter对象, 然后将路由规则传给这个对象 let router = new VueRouter({ routes, //简写 }) // 4. 创建router-link 标签来指定路由 let App = { data(){ return{ num:100, } // 5. 写路由出口 router-view },template:` <div class="app"> <router-link to="/home">首页</router-link> <router-link to="/course">课程页</router-link> <router-view></router-view> </div> ` } // 6. 创建和挂载根实例,在vue对象中挂载一下 router对象 let vm = new Vue({ el:'#app', router, // 挂载 components:{ App, } }) </script> </html>
本文来自博客园,作者:长情不羁的五年,转载请注明原文链接:https://www.cnblogs.com/fivenian/articles/14105481.html