计算属性-computed
vue使用,不推荐在模板中来写过多的逻辑
<h3>{{ n1+n2 }}</h3>
如果对于一个结果,进行计算,可以使用vue提供的计算属性来完成,而且计算属性还具有缓存功能
如果你的依赖项,没有发生改变,则它会再一次调用时,会读取缓存中的数据
//计算属性 computed:{ //调用时,直接写名称就可以,不用写小括号 // 计算属性中的依赖项,可以是一个,也是可以N个,取决于你在计算属性中调用多少 // 注:此方法中不能写异步 // 简写 使用最多的写法 total(){ console.log('computed -- total') //在计算属性中,调用了 n1和n2,则n1和n2就是它的依赖项,如果这两个依赖项,有一个发生改变,则它会重新计算,如果两个都没有发生改变,则第2之后调用,读取缓存中的数据 return this.n1+this.n2 } }
//标准 total:{ //简写只是实现了get get(){ return this.n1+this.n2 }, set(newVal){ if(newVal>10){ this.msg='值有点大' } } }
methods:{ sum(){ //如果定义的计算属性为简写方式,则给计算属性赋值会报错 //只有标准的写法时,它才可以对于计算属性进行赋值操作 //赋值只会触发标准方式中的set方法,然后可以得到它,完成一些别的工作 if(this.total>6){ this.total=101 } return this.n1+this.n2 } }
监听器
const vm = new Vue({ el:"#app", data:{ username:'aaa', errorUsername:'', user:{id:100,name:'aaa'} }, //监听器,它用来监听data配置中数据的变化,一旦有变化,就会自动触发,默认情况,初始化不触发 //在监听器中是可以得到this对象的 //监听它的依赖项,只有一个,一对一 //监听器可以写异步 watch:{ // 方法名或属性名 就是你要观察的data中的属性名称 //标准写法 username:{ handler(newValue,oldValue){ if(newValue.length>=3)this.errorUsername='账号过长' else this.errorUsername='' }, //初始时,执行1次 一般情况下,不启用 只有在标准写法下面,才有此配置 immediate:true } 简写 username(newValue,oldValue){ if(newValue.length>=3) this.errorUsername='账号过长' else this.errorUsername='' } //监听对象中的指定的属性数据的变化 推荐如果你监听的是一个对象中数据变化,建议这样的方式 'user.id'(newValue,oldValue){ console.log(newValue,oldValue) } // 监听对象,只能使用标准方式来写 // 监听对象变化,它的前后值是一样的,无法区分 user:{ //深度监听 deep:true handler(newValue,oldValue){ console.log(newValue,oldValue) } } })
过滤器
过滤器的作用就是为了对于界面中显示的数据进行处理操作
定义过滤器的方案有2种:全局 局部
全局过滤器
参数1:过滤器的名称,可以随意起名
参数2:回调函数,回调函数中的参数最后要有一个,最后1位参数,永远指向要过滤的数据
Vue.filter('phoneCrypt',value=>{ return value.slice(0,3)+'~~~'+value.slice(7) }) Vue.filter('phoneCrypt',(value,salt='****'))
const vm=new Vue({ el:"#app", data:{ phone:'12344431224' }, filters:{ phoneCrypt(value,salt='****'){ return value.slice(0,3)+salt+value.slice(7) } }, methods:{ showPhone(){ return this.phone.slice(0,3)+'****'+this.phone.slice(7) } } })
混入
js是单继承 通过混入能实现多继承
混入:用于公共代码复用
方式: 全局 局部
混入的配置,它可以把几乎所有new Vue配置中的所有配置都能混入,但是el配置他不可以混入
data配置,在混入方式中,只能写函数的方式,
且函数一定要返回一个对象,混入可能被调用多次,如果直接是对象的话,就会有污染
data混入的优先级 组件>局部>全局 =>只会调用一个
生命周期方法,执行顺序: 全局->局部->实例 依次执行
Vue.mixin({ data(){ return{ name:'张三--全局' } }, computed:{ showName(){ return 'abc--全局' } }, methods:{ run(){ return 'run--全局' } }, cerated(){ console.log('created--全局') } })
局部混入
const mix=({ data(){ return { name:'张三--局部' } }, computed:{ showName(){ return(){ 'abc--局部' } }, methods:{ run(){ return'run--局部' } }, created(){ conasole.log('created--局部') } } })
实例
const vm=new Vue({ el:"#app", data:{ name:'张三--实例' }, mixins:[mix], methods:{ run(){ return 'run--实例' } }, created(){ console.log('created--实例') } })
js class的私有属性
#x #y
symbol
...数组
插件
在vue中提供了插件机制,可以通过它的要求来完成插件的封装
Vue.use(函数|类|对象,[可选参数]) 函数 function plugin(Vue类,options可选参数){} 类 必须有一个静态方法 class Plugin{ //必须是静态方法,名称必须位install static instsll(Vue类,options可选参数){} } 定义静态属性
实例生命周期(页面钩子函数 11个)
-
beforeCreate 在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了 执行1次
-
created 在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来 执行1次 用this对象
-
beforeMount 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已 执行1次
-
mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面可以进行数据请求等 执行1次
-
beforeUpdate 数据更新时调用,页面上数据还是旧的 n次
-
updated 由于数据更新完毕,页面上数据已经替换成最新的 n次
-
beforeDestroy 实例销毁之前调用 执行1次
-
destroyed 实例销毁后调用 执行1次
-
activated keep-alive 组件激活时调用
-
deactivated keep-alive 组件停用时调用
-
errorCaptured 当捕获一个来自子孙组件的错误时被调用
render优先级最高 template el
beforeCreate没有把数据劫持,可以使用this,但是得不到this里面的fordata、message等
created 可get 页面还没显示出来
beforeMount 数据整理好了 此页面没有内容,还是js对象
mounted 得到真实dom 建议在这写ajax
8个都生效 3个特定组件生效(错误收集)
const vm=new Vue({ el:"#app", data:{ }, //初始化阶段生命周期 执行1次 beforeCreate(){ }, created(){ }, beforeMount(){ }, mounted(){ }, //更新阶段生命周期 执行n次 beforeUpdate(){ }, updated(){ }, //销毁阶段 只执行1次 beforeDestory(){ }, destroyed(){ } })
网络请求
xhr.readyState状态值 0~4
204返回没有响应体
ajax
mounted() { const xhr = new XMLHttpRequest() xhr.open('get', '/mock/users.json', true) // xhr.onreadystatechange = function () { // // 0 - 4 xhr.readyState状态值 // if (xhr.readyState === 4 && xhr.status === 200) { // console.log(JSON.parse(xhr.responseText)); // } // } xhr.onload = ()=>{ // console.log(JSON.parse(xhr.responseText)); this.users = JSON.parse(xhr.responseText) } xhr.send(null) }
fetch
/* mounted() { fetch('/mock/users.json') .then(ret => ret.json()) .then(json => this.users = json) } */ /* async mounted() { let ret = await fetch('/mock/users.json') this.users = await ret.json() } */ async mounted() { this.users = await (await fetch('/mock/users.json')).json // fetch('url', { // method: 'post', // body: JSON.stringify({ id: 1 }), // headers:{ // 'content-type':'application/json' // } // }) }
fetch 接收两个参数
-
第一个参数是 URL 地址
-
第二个参数是请求的配置信息,包含headers、请求类型(GET/POST)、是否跨域等信息
状态码 面试
状态码类别 1XX(信息性状态码)表示接收的请求正在处理 2XX(成功状态码)表示请求正常处理完毕 3XX(重定向状态码)表示需要进行附加操作以完成请求 4XX(客户端错误状态码)表示服务器无法处理请求 5XX(服务器错误状态码)表示服务器处理请求出错 常见状态码 200 OK——客户端发来的请求在服务器端被正常处理 在响应报文中,随状态码返回的信息会因方法的不同而改变。比如,使用GET时对应请求资源的实体会作为响应返回;使用HEAD时,在响应中只返回首部,不返回实体的主体部分。
204 No Content——服务器接收的请求已成功处理,但返回的响应报文中不含实体的主体部分,即无资源可返回 一般在只需从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用。
206 Partial Content——服务器成功执行了客户端发来的范围GET请求 301 Moved Permanently——永久重定向(请求的资源已被分配新的URL,以后应使用资源现在所指的URL) 302 Found——临时重定向(请求的资源已被分配新的URL,希望用户本次使用新的URL) 303 See Other——由于请求对应的资源存在着另一个URL,应使用GET方法定向获取请求的资源 与302功能相同,但不同点在于303要求使用GET方法获取资源。
304 Not Modified——客户端发送附带条件的请求时,,服务器端允许请求访问资源,但请求未满足条件 304其实与重定向没有关系。
307 Temporary Redirect——临时重定向,但请求方式不会从POST变为GET 与302含义相同,但是302规定的禁止POST变为GET并不被遵守,而307严格遵守不会从POST变为GET。
400 Bad Request——请求报文中存在语法错误 401 Unauthorized——发送的请求需有通过HTTP认证的认证信息 当浏览器初次接收401,会弹出认证用的对话窗口;若之前已进行过1次请求,则表示用户认证失败。返回含有401的响应必须包含一个适用于被请求资源的WWW-Authenticate首部用以质询用户信息。
403 Forbidden——对请求资源的访问被服务器拒绝了 404 Not Found——服务器上无法找到请求的资源 500 Internal Server Error——服务器在执行请求时发生错误 503 Service Unavailable——服务器暂处于超负载或正在进行停机维护,现在无法处理请求
4开头的状态码,在后端接口正确的时候,一般是前端的问题、
5开头的状态码,基本都是后端的问题
200就是OK
其他的都不常见
axios
1、引入
2、console.log(axios)
const vm=new Vue({ el:'#app', data:{ users:[] }, mounted:{ axios.get('/mock/users.json').then(ret=>{ console.log(ret.data); }) } })
axios 全局配置
配置公共的请求头
axios.defaults.baseURL = 'https://api.example.com';
配置 超时时间 毫秒数(0 表示无超时时间)
axios.defaults.timeout = 1000;
promise不能try catch
监听前面所有的异常
axios.get('/api/users').then(ret=>{ console.log(ret.data) }).catch()=>console.log('有异常')
监听自己的异常
axios.get('/api/users').then(ret=>{ console.log(ret.data) },()=>console.log('有异常'))
接口规范restful graphql 面试
patch 增量更新
put全量更新
app.post('/api/users', (req, res) => { // 接受post提交过来的数据 const user = { ...req.body, id: Date.now() } users.push(user) res.send({ code: 0, msg: 'ok', data: users }) }) app.put('/api/users/:id', (req, res) => { // 接受修改的id号 let id = req.params.id // 接受put提交过来的数据 users = users.map(item => (item.id == id ? { ...item, ...req.body } : item)) res.send({ code: 0, msg: 'ok', data: users }) }) app.delete('/api/users/:id', (req, res) => { // 接受修改的id号 let id = req.params.id users = users.filter(item => item.id != id) res.send({ code: 0, msg: 'ok', data: users }) })
一般通过请求头传参
axios.post('/api/users', { name: '李四' }, { headers: { token: 'abc' } }).then(ret => { console.log(ret.data); })
axios拦截器
拦截器 =>中间件
请求拦截器 回调函数中的config对象一定要return出去
axios.interceptors.response.use(config=>{ if(config.method==='get'){ config.headers.token='abc' } return config })
响应拦截器
axios.interceptors.response.use(res=>{ console.log(res) if(res.data.code===0)return res.data alert('有错') },err=>Promise.reject(err))
html中的template标签中的内容在页面中不会显示。但是在后台查看页面DOM结构存在template标签。这是因为template标签天生不可见,它设置了display:none;属性。
不解析,但占位,可写指令
<template></template>
vue组件
组件是html、css、js的聚合体
组件化:
-
将一个具备完整功能的项目的一部分分割多出使用
-
加快项目的进度
-
可以进行项目的复用
组件注册分为:全局注册和局部注册
全局组件
一旦声明完成,就可以在所有的组件中直接使用,无需引入和注册
data必须函数方式 el不能用
定义的组件元素必须要有一个顶层元素进行包裹,否则报错
Vue.component('组件名称',{})
let vnode=h('标签',标签里有哪些属性,子元素)
Vue.component('mytitle',{ render(h){ //不直观但优先级最高 let vnode=h('h3',{attrs:{name:'abc',style:'color:red'}},'我是标签') return vnode } })
Vue.component('mytitle',{ data(){ return{ title:'我是标题' } }, tamplate:` <div> <h3 name='abc' @clcik="setTitle">{{title}}</h3> <div>aaaa</div> //组件里可以嵌套组件 <subtitle></subtitle> </div> `, methods:{ setTitle(){ this.title=Date.now() } } }) //子组件 Vue.component('subtitle',{ template:`<div> <h3>我是子标题</h3> </div> ` })
通过插件形式定义全局组件
const myTitleCmp=Vue=>{ Vue.component('mytitle',{ data(){ return{ title:'我是标题' } }, tamplate:` <div> <h3 name='abc' @clcik="setTitle">{{title}}</h3> <div>aaaa</div> //组件里可以嵌套组件 <subtitle></subtitle> </div> `, methods:{ setTitle(){ this.title=Date.now() } } }) //子组件 Vue.component('subtitle',{ template:`<div> <h3>我是子标题</h3> </div> ` }) } Vue.use(myTitleCmp)