有xss风险
computed:有缓存效果,data中的值不变则不运行
在监听数组对象时,监听不到内部的变化,只有打开深度监听
在watch中添加:deep:true
watch: {
name(oldVal, val) {
// eslint-disable-next-line
console.log('watch name', oldVal, val) // 值类型,可正常拿到 oldVal 和 val
},
info: {
handler(oldVal, val) {
// eslint-disable-next-line
console.log('watch info', oldVal, val) // 引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
},
deep: true // 深度监听
}
}
<template>
<div>
<p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
<p :class="[black, yellow]">使用 class (数组)</p>
<p :style="styleData">使用 style</p>
</div>
</template>
<script>
export default {
data() {
return {
isBlack: true,
isYellow: true,
black: 'black',
yellow: 'yellow',
styleData: {
fontSize: '40px', // 转换为驼峰式
color: 'red',
backgroundColor: '#ccc' // 转换为驼峰式
}
}
}
1.区别
v-if是条件渲染
v-show:只是添加了display:none
使用频繁用v-show,因为v-if会使页面重排
event.proto.constructor 是原始的构造函数
taget
currenttagt
event是原生的
2事件被挂载到当前元素
v-model可以是数组,多选的话,值由value来控制
:属性=value
props:['属性']
this.$emit('自定义事件名',val)
自定事件名 = '下面函数名' //这里时不要写参数的,参数在methods的函数写
总结:以左边为媒介
调用事件
event.$emit('自定义事件名',val) //注意和父子传值区别,event
event.$on('自定义事件名',触发的函数名) //绑定事件
beforeDestory(){
event.$off('自定义事件名',触发的函数名) //及时销毁,以免内存泄漏
}
Vue是异步渲染
data改变之后不会立刻渲染, 所以如果下一步直接获取dom的话, 获取到的是还没有更新的dom
this.$nextTick是页面渲染完后的一个回调,以获取最新的dom节点
$ref:用来获取dom元素
this.$nextTick(()=>{
this.$ref.node
})
默认值可以再slot里随便写的
是为了从子组件获取数据
//子组件
//父组件
{
{scope.自定义名}}
为了插入指定插槽,当插槽多时
//子组件
//父
根据不同的组件名,渲染不同的组件
什么时候用到再去加载,如果一开始就加载导致进入页面慢
<自定义组件 v-if='false'>
components:{
自定义组件:()=>import('../aas/ddd') //当false变成true再引用
}
缓存组件
频繁切换,不需要渲染(tab栏
vue性能优化
tab栏 //组件内的组件,切出去后不会被销毁 //与v-show相比,更适合复杂的切换
state
getter
mutation
action
懒加载
hash和history,后者必须服务端支持
配置路由时
{path:login/:id
components:()=>import('../aas/ddd')
}
很久以前的组件化
传统组件只是静态改变了数据,跟新依然要操作dom
数据驱动视图(mVVM,setState)
vue-mVVM
react-setState
view----viewmodel—model
template data
原理上就是,单纯的改变属性是无法直接响应,
而是要触发个函数才会影响视图
const data = {name :"lisi"};
Object.defineProperty(data, "name", {
get: function () {
console.log("get"); //获取date.name时会触发这个函数
return name;
},
set: function (newval) {
console.log("set"); //给date.name赋值时触发set
name = newval;
},
});
console.log("data :>> ", data);
data.name = "wocao";
需要递归到底
// 重新定义属性,监听起来
function defineReactive(target, key, value) {
// 深度监听
observer(value)
// 核心 API
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if (newValue !== value) {
// 深度监听
observer(newValue)
// 设置新值
// 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
value = newValue
// 触发更新视图
updateView()
}
}
})
}
需要递归到底,计算量大
无法监听新增属性和删除属性(Vue.set Vue.delete)
Object.defineProperty无法监听数组,这时要重新定义数组原型
//创建对象 将对象原型指向数组原型 可以在对象上扩展新的方法而不影响原始原型
const arrproto = Object.create(Array.prototype);
['push',"shift"].array.forEach(element => {
arrproto[element]=function(){
console.log("跟新视图");
//执行原始push
Array.prototype[element].call(this,...arguments)
//this指向函数调用者,
}
});
//监测为数组是,把他的原型换成自定义原型
target.protype = arrproto
vdom:用js模拟dom结构,js运行快,计算出最小的变更,操作dom .diff则是比较vdom
snabbdom来学习vdom
diff算法 diff:对比
2js可diff
2树可diff,如vdom
树dif的复杂度
两颗树做比较,每个节点都互相做比较,就会比较n的平方次, 还排序就是n3次方,算法不可以
解决
只比较同层
tag不同直接删掉重建,不深度比较
tag和key,都相同,则认为是相同节点,不深度比较
js的with语法
vue template complier 将模板编译成render函数
执行render函数生成vnode,patch(diff算法)可将vnode渲染成html
vnode为dom的js版,也就是虚拟dom
总结
初次渲染
跟新过程
响应式(紫色):监听属性,更改属性会通知,看看是不是之前收集过
模板渲染(黄色):执行render会触发getter,收集依赖
虚拟dom(绿色)
异步渲染
hash
网页组成部分
特点
hash变化
H5history
总结
hash—window.onhashchange
history—history.pushState 和 window.onpopstate
v-show是加了dispaley:none的显示隐藏
v-if是条件渲染销毁,而不是显示隐藏
使用频繁用v-show
增强性能,diff算法,判断tag和key, 如果都相同 ,就判断为 是相同的节点, 就不会再向下比较
不能使用index和random
beforecreated new Vue 初始化生命周期和事件完
created 初始化注入和校验完
beforemounted vm.$mount(el)指定el元素 指定template模板 将template编译到render渲染函数
mounted 创建vm.$el替换el ,页面渲染挂载完成
beforeupdataed data被修改后
updataed 跟新完成,data改变,虚拟dom重新渲染
beforedestory vm.$destory后
destory 销毁子组件及事件监听器 解除绑定
子组件先于父组件
组件render函数,渲染虚拟dom的过程中,会触发getter,getter将收集这个属性监听起来. 当data中属性发生改变,触发setter, 会通知,有没有收集了这个属性, 有的话,这重新渲染vdom
通过input事件 this.data=$evnet.target.value
:value=data
改变data, 触发render,重新渲染
数据驱动视图
view = >监听 => model
view <=指令<=model
缓存,data不改变就不执行
vue文件,本质是个构造函数. 当实例化两个,改变data值时, 如果data是对象, 那么另一个的data也会改变. 但如果是函数,返回的是个全新的数据对象
mounted
因为 生命周期是单线程 , ajax是个异步 , 如果放mounted之前 , 他也会排到队列里 , 等渲染完成
mixin
加载大组件
路由异步加载
需要用时再去加载
给组件缓存
想tab栏静态
解绑事件 event.$off
清除计时器
解绑自定义dom事件 如 window scroll
可以拿到父组件的数据
v-slot=‘scope’
slot :scope=‘data’
action处理异步,mutation处理同步
mutation更多是单个操作
action可以整合多个mutation
hash
history(需后端配合)
components:()=>(import ‘…/’)
dd
{
tag:div,
props:{
classname:aa
}
children:[
{
tag:text
style:cloor:red
children:aa
}
]
}
Obeject.difineProperty
深度监听:递归调用
监听数组:自定义数组原型 Array.property.
监听data变化
组件渲染更新流程图
o(n)
原本是n的3次方
通过同层级比较,以及tag和key进行优化
异步渲染(合并data修改),为了提高性能
nexttick是组件渲染完的回调函数,用来拿到最新的dom
v-if 和 v-show
computed
v-for key , 避免 v-for 和v-if同时用
自定义事件\ dom事件 及时销毁
异步组件
keeplive
data层级不要太深, 底层监听会 递归 ,影响性能
webpack
前端通用,如 图片懒加载
ssr
简述diff算法的过程
如何将组件所有props穿给子组件
$porps
v-bind = “prop”
如何自己实现v-model