v-if :
条件渲染。 如果不满足条件,则该元素不会添加到DOM树中
v-if
有更高的切换性能 , 因为当条件为false时v-if不会渲染,当条件为true时才会渲染v-show:
显示与隐藏。 只是修改元素的display属性值
v-show
有更高的初始渲染消耗 , 因为v-show无条件渲染的,本质只是修改了css的样式 生命周期
: v-show
由false变为true不会触发组件的生命周期
v-if
: 由false变化为true时触发组件的beforeCreate
, create
、beforeMount
、mounted
钩子,由true变为false的时候触发组件的beforeDestory
、destoryed
方法
注意点
v-show 不支持 元素,也不支持 v-else。
重点
: v-for的优先级比v-if的优先级高, 如果你有多个元素要进行循环,v-if
就要执行多次
为啥组件中data是一个函数=>return 相当于=>new Object
注意
根实例对象data可以是对象也可以是函数(根实例是单例),不会产生数据污染情况
scoped作用:
scoped工作原理:
App.vue父组件
<home
v-for="item in list"
:key="item.goodSid"
:goodSid="item.goodSid"
:goodsPrice="item.goodsPrice"
:goodsName="item.goodsName"
@price="addClick"
>
</home>
home.vue子组件
进行修改父组件的值
methods: {
icreduce() {
this.goodsPrice--;
},
},
违反了单一数据流原则
this.$emit('事件名',事件参数)
官网解释 : 关于只改变子组件不改变父组件值的两种方式
真实dom与虚拟dom对比:
(真实dom) : 储存几百个属性
(虚拟dom) : 只存储元素中核心的十几个属性
虚拟dom是如何工作的
diff算法对比新旧vnode
只更新变化的部分
给元素添加唯一标识符,可以让vue更准确的渲染元素
vue会把页面DOM转换为虚拟dom , 当数据变化的时候,vue会使用diff算法对比新旧虚拟DOM
当两个盒子元素是一致的时候,vue不会更新元素,而是直接复用
如果给元素添加唯一标识符key值, vue就会强制更新key值不同的元素
key是每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点
参考有无key的情况下代码更新情况
<div id="app">
<li v-for="(item, index) in list" >
<input type="checkbox" :value="item.text" /> {{item.text}}
</li>
</ul>
<button @click="remove"> 删除</button>
</div>
<script>
/* 创建vue实例 */
let app = new Vue({
//el:挂载点
el: "#app",
//data: 要渲染的数据
data: {
list: [{
id: 1,
text: '第一个值'
}, {
id: 2,
text: '第二个值'
}, {
id: 3,
text: '第三个值'
}]
},
methods: {
remove() {
// shift只做删除第一个数据
this.list.shift()
}
}
})
</script>
值发生了改变但是数据没有做到响应式解决方法
直接进行赋值处理
使用 $set
解决
💘target:要更改的数据源(可以是对象或者数组)
🌹 key:要更改的具体数据
🌹 value :重新赋的值
this.$set(this.list, 2, 100)`
v-for更新检测
数组的方法分为两种
第一种: 会改变原数组的元素值, pop(),push(),shift,unshift,sort(),reverse,splice()
* 这种情况 v-for也会更新
第二种:不会改变原数组的元素值. 例如 slice() 、 filter() 、 concat()等
* 这种情况 v-for不会更新
计算属性注意点:
这个函数一定要写在vue实例的computed对象中
这个函数一定要有返回值,否则计算属性无法渲染
计算属性特点及原理介绍 :
缓存机制(提高性能)
(1)计算属性在第一次使用时,vue会调用一次函数,之后就会将返回值缓存起来
(2)下一次使用计算属性的时候,不会执行这个函数,而是直接从缓存中读取
(3)只有当计算属性中的数据发生变化时,这个函数才会重新执行一次
计算属性与mehods的区别在于
侦听器没有缓存 , 但是计算属性有缓存
侦听器可以进行异步操作 ,但是计算属性不能进行异步
侦听器只能侦听data中的数据 , 计算属性可以不用data中的数据
侦听器没有返回值 ,但是计算属性必须有返回值
计算属性默认会执行一次(进行缓存)但是侦听器只有在第一次数据变化的时候才会执行
侦听可以侦听多个数据的变化但是计算属性只能侦听一个数据的变化
四大阶段八大方法
阶段 | 方法名 | 方法名 |
---|---|---|
初始化 | beforeCreate | created |
挂载 | beforeMount | mounted |
更新 | beforeUpdate | updated" |
销毁 | beforeDestroy | destroyed |
vue初始化阶段执行的四个钩子
阶段名称 | 方法名 | 方法名 |
---|---|---|
初始化阶段 | beforeCreate | created |
挂载阶段 | beforeMount | mounted |
组件生命周期的阶段
生命周期各个阶段所完成的事情
<template>
<div>
<p>{{ message }}</p>
<button @click="changeMsg">改变</button>
<p>我的名字是:{{ name }}</p>
<button @click="doClick">点我改名字</button>
</div>
</template>
<script>
export default {
//数据
data() {
return {
name: "ikun",
age: 12,
message: "hello word",
};
},
//事件
methods: {
changeMsg() {
this.message = "goodbye world";
},
doClick() {
this.name = "黑马李宗盛";
},
},
// 创建了vue实例,但是没有创建data
beforeCreate() {
console.log("----------初始化之前------");
console.log(this);
console.log(this.name);
console.log(this.$el);
},
// 创建了data数据对象但是没有挂载=>
// 可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成,$el 未存在
// 最早可以获取data的钩子, 一般在这里发送Ajax请求
created() {
console.log("----------初始化完成------");
console.log(this);
console.log(this.name);
console.log(this.$el);
this.changeMsg();
},
// vue 实例的 $el 和 data 都已初始化,但是data没有挂载,data.message 未替换。
beforeMount() {
// 创建了`el`但是data还没有挂载
console.log("----------挂载之前------");
console.log(this);
console.log(this.name);
// 脚手架环境获取的undefined html环境可以获取挂载点
console.log(this.$el);
},
// 完成初始化渲染 , 挂载data数据(data.messagec成功渲染)
// 最早可以操作dom的钩子 , 在这里可以进行dom的操作(比如焦点)
mounted() {
console.log("----------挂载完成------");
console.log(this);
console.log(this.name);
console.log(this.$el);
},
beforeUpdate() {
//检测data中的数据变化但是data 数据尚未和最新的数据保持同步。
console.log("--------更新之前------");
},
updated() {
// data中的数据变化,页面和 data 数据已经保持同步了。
console.log("------更新完成-------");
},
beforeDestroy() {
// 组件销毁之前调用 ,在这一步,实例仍然完全可用。
console.log("----------销毁之前------");
},
// 完成组件实例的销毁(注意不是JS内存的回收 , 如果别的组件对其有引用永远都不会进行销毁)
destroyed() {
console.log("-----销毁完成----");
},
};
</script>
前四个阶段游览器打印结果
图解
localStorage
的读取是一次磁盘读取,读取速度远低于vuex的内存读取,为了避免重复读取localStorage
影响性能,需要将localStorage的数据放到vuex里维护。由于vuex是储存在内存里面的,所以刷新页面就会消失,所以要存本地一份,刷新后token从本地获取。
首先在Vue的生命周期中 , 是否指定el
的挂载点 当有template时会直接执行template
下的语法 , 在编译的过程中把template渲染成reader
函数
整个渲染机制流程 : 首先借助抽象语法树(AST)解析标签中写的模板。然后解析模板为render函数后转化为虚拟dom(VNode)再解析成真实DOM , 这样的一个渲染过程
Object.definerProperty
实现双向数据绑定getter与setter
的转化参考例如
: 直接修改数组的某一项(arr[index]='xxx')
vue 不能做响应式处理
使用Vue.set(object , propertyName , value) // 当前对象,属性名 属性值
$route
与$router
的区别$route
是路由信息对象,包括 path,params,hash,query ,fullPath,matched,name
等路由信息参数$router
是路由实例对象
包括路由的跳转方法,钩子函数html , css ,js
,所有的界面内容都是包含在这个主页面中,但是在写的时候,还是要分开写,然后在加载的时候由路由动态载入,单页面的跳转只刷新局部资源Object.defineProperty()
来劫持各个属性之间的setter
和getter
,在数据变动时发布消息给订阅者,触发相应的监听回调,也就是数据和视图同步,数据变化视图也跟着变化,视图变化数据也跟着变化Vue在初始化实例时遍历data中的所有属性,并使用Object.defineProperty
把所有属性转化为getter/setter
。这样当追踪到数据变化时,setter会自动调用
Vue.$set
来调用Object.defineProperty()
处理Vue3使用 Proxy来监控数据的变化,其作用为:用于定义基本操作自定义行为(如:属性查找,赋值,枚举,函数调用等)
nextTick
包装的方法// 修改数据
this.message = "修改后的值";
this.isShow=true // 更新视图
// 此时DOM还没有更新
console.log(this.$el.textContent); // => '原始的值'
this.$nextTick(function () {
// DOM 更新了
console.log(this.$el.textContent); // => '修改后的值'
});
$nexttick()
- 因为vue更新dom是异步的,但是我们要操作更新数据之后的视图就需要
$nextTcik()
keep-alive
主要功能是缓存组件,提升性能
- 可以j减少网络请求,如果当前组件数据量比较大,就可以节省网络请求 >> 提升用户体验
- 举例:如果详情页面之间进行切换,就可以使用keep-alive进行缓存组件,防止同样的数据重复请求
他的三个属性
include
包含要缓存的组件exclude
任何名称匹配的组件都不会被缓存max
最多要缓冲多少个组件在路由中设置keepAlive属性判断是否需要缓存
meta: {
keepAlive: true,
title: '列表页'
}
activated
激活时会被触发deactivated
不激活,退出时触发
- url路径会出现
#
字符Hash值不包括在HTTP请求中
,因此修改当前页面的hash,不需要额外配置
- 游览器自带的API
整个地址重新加载,可以保存历史记录,方便前进后退
- 使用HTML5 API(旧浏览器不支持)和HTTP服务端配置,没有后台配置的话,页面刷新时会出现404
- 1.hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用 window.location.hash 读取。特点:
hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面
。- 2.history模式:history采用HTML5的新特性;且提供了两个新方法:
pushState(), replaceState()
可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更
.stop
阻止事件冒泡.prevent
阻止标签默认行为.once
事件只执行一次(Vue3剔除).enter
:监听键盘enter键Vue.directive
directives
bind
绑定事件的触发inserted
节点插入的时候会触发updata
组件内的相关更新el
:指令所绑定的元素,可以用来直接操作 DOM。state
: 单一状态树,用来存储变量
;getters
: 从基本数据(state)派生的数据,相当于state的计算属性
;mutations
: 提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mution 都有一个字符串的事件类型(type)和一个回调函数(handler)。 state作为第一个参数,提交载荷作为第二个参数
。action
: 和mution的功能大致相同,不同之处在于 ①Action提交的是mution,而不是直接变更状态,②Action可以包含任意异步操作
。dispatch
来触发actions
actions
里面的每一个方法都有一个commit
方法,当方法执行的时候会通过commit
来触发mutations
里面的方法进行数据的修改mutations
里面都有一个state
参数,这样就可以进行数据的修改跳转方法 | 传参位置 | 路由规则 | 接收 |
---|---|---|---|
| /path?key=value | 无特殊 | $route.query.key |
| /path/值 | /path/:key | $route.params.key |
this.$router.push({path: “/path”, query: {key: value}}) | query的对象 | 无特殊 | $route.query.key |
this.$router.push({name: “com”, params: {key: value}) | params的对象 | 路由规则需要name属性 | $route.params.key(注意,这种在内存中保存) |
router.push
this.$route.query
this.$router.push()跳转到指定的url
,并在history中添加记录,点击回退返回到上一个页面this.$router.replace()跳转到指定的url
,但是history中不会添加记录,点击回退到上上个页面this.$touter.go(n)
向前或者后跳转n个页面,n可以是正数也可以是负数
简单理解 :
采用递归,双指针原理,同级比较,深度优先的准则
补丁
的方式,对比新旧两株虚拟DOM树的变更差异,将更新补丁作用于真实DOM,以最小成本完成视图更新;修改准则
:原本没有新版有,则增加;原本有新版没有,则删除;都有则进行比较,都为文本结点则替换值;都为静态资源不处理;都为正常结点则替换相同点:都是语法糖,都可以实现父子组件中的数据的双向通信
。
v-model语法糖 = props父传子 + 绑定事件监听@input
<input type='text' :value="msg" @input = "msg = $event.target.value"/>
<span>{{msg}}</span>
v-model
父组件通过子组件标签传值,子组件通过$emit触发<!--v-model简写-->
<Son v-model="msg" />
<!--原始写法-->
<Son :value="msg" @input= "val => msg=val "/>
props:['value']
xxx.sync的原理
①父组件给字子组件传递props:属性名
②给当前子组件绑定了一个自定义事件,事件名为update:属性名,该事件会更新xxx的值
不同点:
// 正常父传子:
<son :info="str" :title="str2"></son>
// 加上sync之后父传子(.sync没有数量限制):
<son :info.sync="str" .title.sync="str2"></son>
// 它等价于
<son
:info="str" @update:info="val=>str=val"
:title="str2" @update:title="val=>str2=val"></son>
子组件
<template>
<div>
<p>{{ info }}</p>
<button @click="fn">修改数据(子)</button>
</div>
</template>
<script>
export default {
props: ["info","title"],
name:'son',
methods: {
fn() {
// 修改数据:`$emit`所调用的事件名必须是`update:属性名`
this.$emit('update:info',this.info + ",我现在被子组件emit了")
},
},
};
</script>
- 格式不同: v-model=“num”, :num.sync=“num”
- v-model:
@input + value
- :num.sync:
@update:num
v-model只能用一次;.sync可以有多个
注意点
vue3中取消了修饰符.sync
,并且把.sync的功能合并到了v-model上。
更新循序
- 先父组件(beforeUpdata)
- 子组件beforeUpdata,Updata
- 再父组件 updata
销毁循序
- 父组件beforeDestroy
- 子组件 beforeDestriy destroyed
- 父组件 destroyed
通过
webpack
对项目体积进行压缩,开启gizp
压缩文件
2. 减小图片体积,图标可通过矢量图来代替
- 通过精灵图来减少小图标的总请求数
单页面应用的首屏加载较慢主要是因为单页面应用在首屏时,
无论是否需要都会加载所有的模块
,可通过按需加载、路由懒加载
来优化。
Vue.component
方法注册组件,子组件需要数据,可以在props
中接受定义,$emit
方法向外抛出slot
methods
选项中开放方法 Vue.use
注册全局组件
Vue 插件机制的原理:本质上插件就是一个对象,在对象里面调用install
方法
import XtxSkeleton from '@/cpn/skeleton/index.vue';
import { App } from 'vue';
export default {
install(app:App){
app.component('XtxSkeleton', XtxSkeleton)
}
}
>路由传参分为 params 传参与 query 传参
params 传参类似于网络请求中的 post 请求,
params 传过去的参数不会显示在地址栏中(但是不能刷新)。
params 只能配合 name 使用,如果提供了 path,params 会失效。
query 传参类似于网络请求中的 get 请求,
query 传过去的参数会拼接在地址栏中(?name=xx)。
query 较为灵活既可以配合 path 使用,也能配合 name 使用(亲测可用)。
eventBus
,provide和inject
,vuex
- 代码执行顺序
data->provide->created->mounted
* provide 和 inject 绑定并不是可响应的
// 传入data中的数据必须return
//grandpa
components: { Son },
provide(){
return {
grandpaMsg:this.message
}
},
// 要想实现一个响应式 必须reeturn 一个函数
provide(){
return {
grandpaMsg:()=>this.message
}
},
component组件
:有两个属性—is inline-template
渲染一个‘元组件’为动态组件,按照’is’特性的值来渲染成那个组件
transition组件
:为组件的载入和切换提供动画效果,具有非常强的可定制性,支持16个属性和12个事件
transition-group:
作为多个元素/组件的过渡效果
keep-alive
:包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
slot
:作为组件模板之中的内容分发插槽,slot元素自身将被替换
Composition API(组合 API)
,相比较 Vue2 的 options api,对于开发大型项目更利于代码的复用和维护。新特性,例如 Fragment、Teleport、Suspense 等。MVC : 传统的设计模式。
数据双向绑定
让数据自动地双向同步 不再需要操作DOM
MVVM是Model-View-ViewModel
的简写
- MVVM是组织与管理我们代码的方法,在MVVM中View和model不能直接通信,一定要通过ViewModel,
- ViewModel实现了一个
观察者
的角色,每当Model更新的时候ViewModel需要监听
他,并通知相应的View做UI更新- 那同样当用户操作View的时候,ViewModel也要
获取数据上的变化,并通知Model进行数据的更新,这样就实现了数据的双向绑
2xx
(成功)表示成功处理了请求的状态码
200
(成功)服务器已成功处理了请求。301
永久重定向401
没有认证, 没有登录网站(token过期
)403
禁止访问 ,没有权限404
服务器找不到请求网页,请求地址错误
500
,(服务器内部错误)服务器遇到错误,无法完成请求
<script>
/* 学习目标:XMLHttpRequest的两个事件
1. onload事件 : 接收服务器响应的数(一次请求,只会执行一次)
2. onreadystatechang事件 : 作用与onload事件一致(一次请求,会执行多次)
面试点: XMLHttpRequest对象的状态码 (xhr.readyState)
0: 请求未建立 (创建了xhr对象,但是还没调用open)
1: 服务器连接已建立
2. 请求已接收 (send之后,服务器已经接收了请求)
3. 请求处理中
4. 请求已完成,且响应已就绪 ( 4状态码等同于onload事件 )
*/
//(1).实例化ajax对象
let xhr = new XMLHttpRequest()
console.log(xhr.readyState)
//(2).设置请求方法和地址
xhr.open("post", "http://www.liulongbin.top:3009/api/login")
//(3).设置请求头(post请求才需要设置)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
console.log(xhr.readyState)
//(4).发送请求 : 参数格式 'key=value'
xhr.send("username=admin&password=123456")
//(5).注册回调函数
//a. onload 是新式浏览器才支持的
//b. 如果要兼容更早的浏览器,可以使用 onreadystatechange
//c. onreadystatechange触发时机 : xhr.readState状态变化
// xhr.onload = function() {};
xhr.onreadystatechange = function() {
console.log(xhr.readyState)
//onreadystatechange会触发多次,一般需要判断xhr.readState == 4 才获取响应数据
if (xhr.readyState == 4) {
console.log(xhr.responseText)
}
}
</script>
get
在url后面拼接(请求行)post
在请求体传参
get
有大小限制(一般在2-5MB)post
没有大小限制
get
传参直接暴露在url中,不安全 (一般查询类都是get)post
参数在请求体重,更加安全(一般用于登录注册必须是post请求)
get 传输速度更快 ,post比较慢
1.第一次请求为options
预检请求,状态码为:204
2.第二次为真正的post
请求
HTTPS 协议需要到 CA (Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用。(以前的网易官网是http,而网易邮箱是 https 。)
HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。
HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
HTTP 的连接很简单,是无状态的
。HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。(无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。)
详细参考
cookie
相当于前端的token 但是session
相当于key,这个key
会返回给后端并存储在数据库redis
中1、
cookie
数据存放在客户的浏览器上,session
数据放在服务器上。
2、cookie
不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
3、session
会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K
,很多浏览器都限制一个站点最多保存20个cookie。
- cookie 是网站为了标示用户身份而储存在用户本地终端上的数据(通常经过加密)
- cookie 始终会在同源 http 请求头中携带(即使不需要),在浏览器和服务器间来回传递
- sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存
cookie
数据根据不同浏览器限制,大小一般不能超过4k
sessionStorage 和 localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M
或更大
localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据
sessionStorage 数据在当前浏览器窗口关闭后自动删除
cookie过期时间是后端决定的,与浏览器是否关闭无关
Set-Cookie的响应头
,客户端会根据这个响应头存储Cookie信息。再次请求服务器时,客户端会在请求信息中包含一个Cookie请求头,而服务器会根据这个请求头进行用户身份、状态等较验。方法 | 描述 |
---|---|
GET | 请求指定的页面内容,并返回实体主体 |
HEAD | 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 |
POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件 )。数据包含在请求体中。POST请求可能会导致新的资源的建立或者已有资源的修改。 |
PUT | 从客户端向服务器传送的数据取代指定的文档的内容 |
DELETE | 请求服务器删除指定的页面 |
CONNECT | HTTP1.1协议中预留给能够将连接方式改为管道方式的代理服务器 |
OPTIONS | 允许客户端查看服务器的性能 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
1. 客户端向服务端发送一个 `FIN`包,自己进入终止等待一状态 (挥手)
2. 服务端向客户端发送`ACK`包,表示自己进行等待关闭状态,客户端进入终止等待二状态 (二次挥手), 此过程中服务端还可以向客户端发送未发送的数据,而客户端还可以接受数据
3. 待客户端接受数据完后,服务端向客户端发送`FIN`包进入最后的确认状态
4. 客户端收到之后回复`ACK`包进入超时登录状态,经过超时时间后关闭连接
A:分手吧 B:好吧
B:是我不够帅吗?
A : 是的
const src =
"data:image/png;base64," +
btoa(
new Uint8Array(res).reduce(
(data, byte) => data + String.fromCharCode(byte),
""
)
);
这样图片可直接使用img标签显示出来
*2 , 然后使用url encode
加密base64图片
url encode.encode(src)
; // 默认是’UTF-8’
提升用户的体验
,如果图片数目较多,等待时间较长,严重影响用户的体验减少无效资源的加载
这样能明显减少服务器的压力和流量,防止资源过多阻塞JS的加载
,影响网站的正常使用
- 首先将页面上的图片的 src 属性设为空字符串,而图片的真实路径则设置在
data-original
属性中,- 当页面滚动的时候需要去监听scroll事件,在scroll事件的回调中,判断我们的懒加载的图片是否进入可视区域,如果图片在可视区内将图片的 src 属性设置为
data-original
的值,这样就可以实现延迟加载。
预加载: 也是一种性能优化的技术,预加载简单的说就是将所需的资源提前请求加载到本地,这样后面就可以直接在缓存中取资源
在网页全部加载之前,对一些主要内容进行加载,`以提供给用户更好的体验,减少等待的时间。否则,如果一个页面的内容过于庞大,没有使用预加载技术的页面就会长时间的展现为一片空白,直到所有内容加载完毕。
SSR是服务端渲染
:在后台将vue实例渲染为HTML字符串直接返回,在前端激活为交互程序。
优点
缺点 :开发逻辑复杂,服务器负载大
强缓存: 指的是 让浏览器强制缓存服务端提供的资源。 使用Cache-Control 中的 max- age 字段
来指定缓存时间
协商缓存,主要由 ETag 和 Last-Modified 两个字段来实现
区别: