过滤器
过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示,值得注意的是过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据。
过滤器分全局过滤器和局部过滤器,下边我着重说下全局过滤器,因为全局过滤器在项目中使用频率非常高!
局部过滤器
过滤器可以用在两个地方:双花括号插值 或 v-bind表达式
<template>
<div>
<input type="number" v-model="money">
<!-- 格式: 要过滤的数据 | 过滤的方法 -->
{{money | filter_price}}
</div>
</template>
<script>
export default {
name: "FilterDemo",
data(){
return {
money:0
}
},
//局部过滤器
filters:{
filter_price(val){
return val+"¥"
}
}
}
</script>
<style scoped>
</style>
全局过滤器
-
将过滤方法放在一个js文件中。 filter.js
let filter_price= function(val){ return val+"¥" } //导出 export {filter_price} -
在main.js中定义全局过滤器
import {filter_price} from './views/过滤器/filter' //Vue.filter(过滤器名字,过滤器方法) Vue.filter("filter_price",filter_price)
另一种导出方式(推荐使用)
import * as filter from './components/过滤器/filter.js'
console.log(filter);
//先把字典中的key全部取出来,然后用forEach循环遍历,使用Vue.filter注册为全局过滤器
Object.keys(filter).forEach(item=>{
Vue.filter(item,filter[item])
});
-
组件中使用过滤器
{{money | filter_price}}
vue生命周期介绍
生命周期示例
InputDemo.vue
<template>
<div>
<p>{{ number }}</p>
<input type="text" name="btnSetNumber" v-model="number">
</div>
</template>
<script>
export default {
name: "InputDemo",
data(){
return{
number:''
}
},
beforeCreate: function () {
console.log('beforeCreate 钩子执行...');
console.log(this.number)
},
created: function () {
console.log('created 钩子执行...');
console.log(this.number)
},
beforeMount: function () {
console.log('beforeMount 钩子执行...');
console.log(this.number)
},
mounted: function () {
console.log('mounted 钩子执行...');
console.log(this.number)
},
beforeUpdate: function () {
console.log('beforeUpdate 钩子执行...');
console.log(this.number)
},
updated: function () {
console.log('updated 钩子执行...');
console.log(this.number)
},
beforeDestroy: function () {
console.log('beforeDestroy 钩子执行...');
console.log(this.number)
},
destroyed: function () {
console.log('destroyed 钩子执行...');
console.log(this.number)
},
}
</script>
<style scoped>
</style>
LiveDemo.vue
<template>
<div>
<InputDemo v-if="show"></InputDemo>
<button @click="show=!show">销毁输入框</button>
</div>
</template>
<script>
import InputDemo from './InputDemo'
export default {
name: "LiveDemo",
data(){
return{
show:true
}
},
components:{
InputDemo
},
}
</script>
<style scoped>
</style>
异步回调函数
ECMAScript 6语法
-
变量
-
var变量
var声明变量的问题:
可以多次重复声明同一个变量名,存在覆盖的风险
在全局声明的变量会挂在全局对象上
var不能形成块级作用域,例如:if、for范围外依然可以使用var声明的变量
var声明的变量具备变量提升(hoisting)特性— 允许使用在前,声明在后
-
let变量
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
{ let a = 10; var b = 1; } console.log(a); console.log(b);上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。
for循环的计数器,就很合适使用let变量。
-
常量const
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable.const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
-
字符串模板
字符串需要用一对反引号包裹起来,它可以定义多行字符串,只用一对反引号
要拼进去的数据需要放在${}里面 大括号里面还可以进行运算, 大括号里面可以调用函数- ES6以前,使用变量和字符串拼接
var name = "王大锤"; var age = 22 var desc =name+",今年"+age+"岁"; console.log(desc)- ES6语法:使用字符串模版,由反引号(波浪那个按键的引号) + ${变量名}
var name = "王大锤"; var age = 22; var desc2 = `${name},今年${age}岁`; console.log(desc2)
-
-
基础语法
-
if判断
-
for循环
在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是:
-
简单for循环
-
for-in
-
forEach
在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循环,是:
- for-of
-
-
函数
- 箭头函数
-
解构赋值
-
promise对象
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
var i=10;
let pro =new Promise(function (resolve,reject) {
console.log("进入promise")
//模拟异步操作成功
if (i>9) {
//成功时,执行resolve中代码
resolve("成功")
}
else {
//失败时,执行reject中代码
reject("失败")
}
});
//pro.then获取到执行成功的结果
pro.then((a)=>{console.log("成功时会执行",a)});
//pro.catch获取到执行失败的结果
pro.catch((a)=>{console.log("失败时会执行",a)});
//pro.finally不管成功还是失败都会执行
pro.finally((a)=>{console.log("不管成功还是失败都会执行",a)});
vue 发送ajax请求
vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现
axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护
-
安装axios并引入
npm install axios -
基本用法
使用之前学习Django时的后端代码,启动后端服务。
使用当时的创建项目的接口作为示例
AppProject.vue
<template> <div> <table> <tr> <td>项目名</td> <td><input v-model="pro_name"></td> </tr> <tr> <td>版本号</td> <td><input v-model="pro_version"></td> </tr> <tr> <td>类型</td> <td><input v-model="pro_type"></td> </tr> <tr> <td>项目状态</td> <td><input v-model="pro_status"></td> </tr> <tr> <td>描述</td> <td><input v-model="pro_description"></td> </tr> <tr> <td colspan="2"> <button @click="sendRequest">提交</button> </td> </tr> </table> </div> </template> <script> import axios from "axios" export default { name:"AppProject", data(){ return { //默认值 pro_name:"", pro_version:"", pro_type:"", pro_status:"", pro_description:"" } }, methods:{ sendRequest(){ // 配置axios的主机、端口 axios.defaults.baseURL="http://localhost:8000"; // 配置请求头信息Content-type axios.defaults.headers.post['Content-type'] = "application/json"; // 请求参数 var myData = { name:this.pro_name, version:this.pro_version, type:this.pro_type, status:this.pro_status, description:this.pro_description }; // post请求 axios.post("/v01/projects/",myData).then((res)=>{ console.log(res.data.code) }).catch(()=>{ console.log("请求失败") } ) } } } </script> <style scoped> </style>效果:
注:
1.提示跨域访问问题,在后端代码中解决:
-
安装django-cors-headers
pip install django-cors-headers -
配置settings.py文件
# 允许访问的主机列表 ALLOWED_HOSTS = ["*"] INSTALLED_APPS = [ ... 'corsheaders', ... ] MIDDLEWARE_CLASSES = ( ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 注意顺序 ... ) #跨域增加忽略 CORS_ALLOW_CREDENTIALS = True CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_WHITELIST = () CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'VIEW', ) CORS_ALLOW_HEADERS = ( 'XMLHttpRequest', 'X_FILENAME', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', )
2.一次提交,会发起两个请求,一个是options请求,解决请求跨域问题,一个是真实的请求
-
-
axio基础配置文件
增加axio基础配置文件,就不用每个请求都去写一遍基础信息
import axios from "axios" import store from "@/store" const service = axios.create({ baseURL:"http://127.0.0.1:8000", //超时时间 timeout:10000 }); //请求拦截器 service.interceptors.request.use( config=>{ if(store.state.data){ config.headers["Token"] = store.state.data } return config }, //发送错误时 err => { console.log(err) return Promise.reject(err) } ); //响应拦截器 service.interceptors.response.use( res=>{ console.log(res) if(res.status==200){ let response =res.data if(response.code == "0000"){ console.log("创建成功") }else { console.log(res.message) }} else { console.log("未知错误") } return res }, //发送错误时 err => { console.log(err) return Promise.reject(err) } ); export default service;AppProject.vue
<template> <div> <table> <tr> <td>项目名</td> <td><input v-model="pro_name"></td> </tr> <tr> <td>版本号</td> <td><input v-model="pro_version"></td> </tr> <tr> <td>类型</td> <td><input v-model="pro_type"></td> </tr> <tr> <td>项目状态</td> <td><input v-model="pro_status"></td> </tr> <tr> <td>描述</td> <td><input v-model="pro_description"></td> </tr> <tr> <td colspan="2"> <button @click="sendRequest">提交</button> </td> </tr> </table> <button @click="addToken">添加token</button> </div> </template> <script> // import axios from "axios" import axios from "./request" export default { name:"AppProject", data(){ return { pro_name:"", pro_version:"", pro_type:"", pro_status:"", pro_description:"" } }, methods:{ sendRequest(){ // axios.defaults.baseURL="http://localhost:8000"; // axios.defaults.headers.post['Content-type'] = "application/json"; var myData = { name:this.pro_name, version:this.pro_version, type:this.pro_type, status:this.pro_status, description:this.pro_description }; axios.post("/v01/projects/",myData).then((res)=>{ console.log(res.data.code) }).catch(()=>{ console.log("请求失败") } ) }, addToken(){ this.$store.commit("setData","abc123456") } } } </script> <style scoped> </style> -
请求对象
{ //“url”是将用于请求的服务器url url:'/user', //“method”是发出请求时要使用的请求方法 method:'get',//默认 //除非“url”是绝对的,否则“baseURL”将位于“url”的前面。 //为axios实例设置'baseURL'可以方便地传递相对url //到那个实例的方法。 baseURL:'https://some domain.com/api/', //“transformRequest”允许在将请求数据发送到服务器之前对其进行更改 //这仅适用于请求方法“PUT”、“POST”和“PATCH” //数组中的最后一个函数必须返回字符串或ArrayBuffer transformRequest: [function (data) { //做任何你想转换的数据返回数据; }], //“transformResponse”允许在 //它传递给then/catch transformResponse: [function (data) { //做任何你想转换的数据返回数据; }], //“headers”是要发送的自定义邮件头 headers:{'X-Requested-With':'XMLHttpRequest'}, //“params”是与请求一起发送的URL参数 params:{ID:12345}; //“paramsSerializer”是负责序列化“params”的可选函数` //(例如,https://www.npmjs.com/package/qs,http://api.jquery.com/jquery.param/) paramsSerializer: function(params) { return Qs.stringify(params, {arrayFormat: 'brackets'}) }, //“data”是要作为请求正文发送的数据 //仅适用于请求方法“PUT”、“POST”和“PATCH” //如果未设置“transformRequest”,则必须是字符串、ArrayBuffer或哈希 data:{firstName:'Fred'}, //“timeout”指定请求超时前的毫秒数。 //如果请求花费的时间超过“timeout”,则请求将被中止。 timeout:1000, //“withCredentials”指示是否跨站点访问控制请求 //应该使用凭据 withCredentials:false,//默认 //“adapter”允许自定义处理请求,从而使测试更容易。 //调用“resolve”或“reject”并提供有效的响应(请参见[响应文档](#响应api))。 adapter: function (resolve, reject, config) { /* ... */ }, //“auth”表示应使用HTTP Basic auth,并提供凭据。 //这将设置一个“Authorization”头,覆盖任何现有的 //使用“headers”设置的“Authorization”自定义标题。 auth: { username: 'janedoe', password: 's00pers3cret' } //“responseType”指示服务器将用其响应的数据类型 //选项有“arraybuffer”、“blob”、“document”、“json”、“text” responseType:'json',//默认 //“xsrf cookie name”是用作xsrf令牌值的cookie的名称 xsrfCookieName:'XSRF-TOKEN',//默认 //“xsrf header name”是承载xsrf令牌值的http头的名称 xsrfHeaderName:'X-XSRF-TOKEN',//默认 //“progress”允许处理“POST”和“PUT uploads”以及“GET”下载的进度事件 progress: function(progressEvent) { //对本机进度事件执行任何操作 } } -
响应对象
{ //“data”是服务器提供的响应 data:{}, //“status”是服务器响应中的HTTP状态代码 status:200, //“statusText”是来自服务器响应的HTTP状态消息 statusText:'ok', //`headers`服务器响应的头 headers:{}, //“config”是为请求提供给“axios”的配置 config:{} }
vue-router路由的使用
什么是路由
路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容。Home按钮 => home 内容, about按钮 => about 内容,也可以说是一种映射. 所以在页面上有两个部分,一个是点击部分,一个是点击之后,显示内容的部分。
点击之后,怎么做到正确的对应,比如,我点击home 按钮,页面中怎么就正好能显示home的内容。这就要在js 文件中配置路由。
路由中有三个基本的概念 route, routes, router。
1, route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮 => home内容, 这是一条route, about按钮 => about 内容, 这是另一条路由。
2, routes 是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, { about按钮 => about 内容}]
3, router 是一个机制,相当于一个管理者,它来管理路由。因为routes 只是定义了一组路由,它放在哪里是静止的,当真正来了请求,怎么办? 就是当用户点击home 按钮的时候,怎么办?这时router 就起作用了,它到routes 中去查找,去找到对应的 home 内容,所以页面中就显示了 home 内容。
4,客户端中的路由,实际上就是dom 元素的显示和隐藏。当页面中显示home 内容的时候,about 中的内容全部隐藏,反之也是一样。客户端路由有两种实现方式:基于hash 和基于html5 history api.
什么是 vue-router?
-
(1)vue-router 是 Vue 官方提供前端路由插件,借助它我们实现可以基于路由和组件的单页面应用。
-
(2)它与传统的页面区别在于:
传统的页面应用采用的是后端路由,即通过超链接来实现页面切换和跳转的。
而在 vue-router 单页面应用中,则是通过路径之间的切换(实际上就是组件的切换)。
vue-router安装
使用vue创建项目时,已经安装了vue-router
基本使用
示例
创建vue项目时,/src/router文件下来默认有index.js文件
import Vue from 'vue'
import VueRouter from 'vue-router'
//关联的组件要导入
import MainApp from "../views/路由控制/MainApp";
Vue.use(VueRouter)
const routes = [
{
path: '/', //路由绑定的路径
name: 'main', //路由的名字
component: MainApp //路由绑定的组件
}
//还有其他路径,用对象形式继续写{path:'',name:'',component:''}
]
// 默认不必修改
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
App.vue
<template>
<div id="app">
路由占位符之上
<!-- 路由占位符 -->
<router-view></router-view>
路由占位符之下
</div>
</template>
<script>
// 1.导入组件
export default {
name: "App",
// 2. 注册组件
components:{
}
}
</script>
<style>
</style>
启动vue应用时,先加载App.vue这个组件,加载完后根据访问的url去匹配路由,路由就会把组件信息显示到路由占位符<router-view></router-view>这个地方。
多个路由
(不同路由展示不同页面的原理)
ChildApp.vue
<template>
<div>这是一个子应用</div>
</template>
<script>
export default {
name: "ChildApp"
}
</script>
<style scoped>
</style>
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import MainApp from "../views/路由控制/MainApp";
import ChildApp from "../views/路由控制/ChildApp";
Vue.use(VueRouter)
const routes = [
{
path: '/main', //路由绑定的路径
name: 'main', //路由的名字
component: MainApp //路由绑定的组件
},{
path: '/child', //路由绑定的路径
name: 'child', //路由的名字
component: ChildApp //路由绑定的组件
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
访问 http://localhost:8081/child
路由跳转
(点击某个按钮跳转到另一个页面的原理)
<router-link to="跳转的path"></router-link>标签,可以通过tag标签来修改样式,默认是tag="a",即超链接。
<template>
<div id="app">
<!-- 路由跳转 -->
<router-link to="/main" tag="button">点击跳转到main</router-link> | <router-link to="/child">点击跳转到child</router-link>
<br>
路由占位符之上
<!-- 路由占位符 -->
<router-view></router-view>
路由占位符之下
</div>
</template>
<script>
// 1.导入组件
export default {
name: "App",
// 2. 注册组件
components:{
}
}
</script>
<style>
</style>
router-link的另一种写法
<router-link :to="{path: '/main'}" tag="button">点击跳转到main</router-link> |
<router-link :to="{path: '/child'}">点击跳转到child</router-link>
使用js的方法来实现路由跳转: (使用this.$router.push())
App.vue
<template>
<div id="app">
<button @click="toMain">main</button>
<br>
路由占位符之上
<!-- 路由占位符 -->
<router-view></router-view>
路由占位符之下
</div>
</template>
<script>
export default {
name: "App",
methods:{
toMain(){
console.log("点击了main按钮")
//使用js实现路由跳转
this.$router.push({
path: "/main"
}
)
}
}
}
</script>
<style>
</style>
路由传参
-
params传参
params传参,路由中必须要一个参数来接受参数
效果
-
query传参
要达到路由中这种形式
/main?id=20的效果,使用query传参效果:
命名路由
前面讲了
动态路由
路由嵌套
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import MainApp from "../views/路由控制/MainApp";
import ChildApp from "../views/路由控制/ChildApp";
Vue.use(VueRouter)
const routes = [
{
//主路由
path: '/main',
name: 'main',
component: MainApp,
// 子路由,它的路由占位符必须写在MainApp中
children:[
//嵌套的路由
{
// 以“/”开头的嵌套路径会被当作根路径,所以子路由上不用加“/”
path: 'child',
name: 'child',
component: ChildApp
}
]
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
MainApp.vue
<template>
<div>
hello world
<!-- 子路由的路由占位符要写在MainApp中 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "MainApp"
}
</script>
<style scoped>
</style>
效果
导航守卫
element 组件库
一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的组件库,提供了配套设计资源,帮助你的网站快速成型。由饿了么公司前端团队开源。
安装
-
安装element`-ui
npm i element-ui -S -
安装依赖包
-
main.js中引入组件库和样式库
-
按需引入:只引入需要的组件,以达到减小项目体积的目的
main.js
import Vue from 'vue'; //引入Button,Select组件 import { Button, Select } from 'element-ui'; //引入组件样式,才能看到效果 import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue' Vue.component(Button.name, Button); Vue.component(Select.name, Select); /* 或写为 * Vue.use(Button) * Vue.use(Select) */ new Vue({ el: '#app', render: h => h(App) });使用:原来的
<button><button/>更换为<el-button @click="toMain">main</el-button>效果:
-
全局引入:引入所有组件,影响性能,小项目不影响
main.js
import Vue from 'vue'; //全局引入ElementUI import ElementUI from 'element-ui'; //引入组件样式 import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue'; // 注册ElementUI Vue.use(ElementUI); new Vue({ el: '#app', render: h => h(App) });
-
layout布局
element是通过基础的24分栏,迅速简便地创建布局,因此我们也成这种布局形式为(24栅格化)
通常我们是通过 row 和 col 组件,并通过 col 组件的 span 属性我们就可以自由地组合布局