从而让 data 的属性能够响应数据变化。
同样,如果要给obj增加一个新属性,如果该属性未在data中声明,页面也不会刷新。也就是vue文档中声明的“Vue 不能检测到对象属性的添加或删除”,同样需要使用vue.set 或者this.$set方法进行赋值才好使。
深拷贝/浅拷贝
先来看一个简单的例子:
let obj = {name:'fiona-SUN'};
let copyObj = obj;
copyObj.name = 'fiona';
console.log(copyObj.name); // 'fiona'
console.log(obj.name); // 'fiona'
在js中也有栈(stack)和堆(heap)的概念:
栈:自动分配的内存空间,大小确定会自动释放。存放变量/局部变量/形参等。在js中存放简单数据段(五种基本数据类型:Number、String、Boolean、Null、Undefined),他们是按值存放的,可以直接访问。
堆:动态分配的内存,大小不定并且不会自动释放。存放在堆内存中的对象,栈中的变量实际保存的是一个指针,这个指针指向堆中的某一个位置。
所以上述例子中,属于浅拷贝,当我们声明一个对象,由于他不属于五种基本数据类型(即非简单数据段
),栈中会存放一个我们声明的obj
变量,它指向了堆中实际的这个对象的地址
。当我们把这个引用地址赋值给了copyObj
,实际它获得的是一个与obj
一致的指向堆中的地址。当copyOjb
改变了指向的对象地址的实际的值的时候,obj
拿到的值也就自然而然变化了。看图理解⬇
es6之展开Object.assign(拷贝obj的内容到一个新的堆内存,copyObj存储新内存的引用)
复制一个对象
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj1.a = 1;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj2.a = 2;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
为大家精心准备了vue课程,微信搜索关注公众号:【zhulin1028】,或者扫描以下二维码,回复【vue课程】即可免费获取。
二、Vue生命周期中的钩子函数
1). 初始化显示(只执行一次)
* beforeCreate()el 和 data 并未初始化
* created() 完成了 data 数据的初始化,el没有
* beforeMount()完成了 el 和 data 初始化
* mounted()完成挂载,获取到DOM节点
2). 更新状态(可执行多次)
* beforeUpdate()
* updated():我们单击页面中的“更新数据”按钮,将数据更新。下面就能看到data里的值被修改后,将会触发update的操作
3). 销毁vue实例: vm.$destory()(只执行一次)
* beforeDestory()
* destoryed()
created()/mounted(): 发送api请求, 启动定时器等异步任务
beforeDestory(): 做收尾工作, 如: 清除定时器,音频播放器
destoryed :销毁完成后,我们再重新改变message的值,vue不再对此动作进行响应了。但是原先生成的dom元素还存在,可以这么理解,执行了destroy操作,后续就不再受vue控制了。因为这个Vue实例已经不存在了。
实例:
vue中的setInterval在页面离开之后仍会执行,在切换多个路由之后,定时器的速度会越来越快
beforeDestory(){
if(this.timer){
clearInterval(this.timer)
}}
总结:用created还是mounted方法看情况,一般放到created里面就可以了,这样可以及早发请求获取数据,如果有依赖dom必须存在的情况,就放到mounted(){this.$nextTick(() => { /* code */ })}
ref
ref
被用来给元素或子组件注册引用信息的静态节点,引用信息将会注册在父组件的 $refs
对象上。
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件,ref和 r e f s 其实就是用来获取 / 操作 D O M 元素的;类似于 j q u e y 中的 refs其实就是用来获取/操作DOM元素的;类似于jquey中的 refs其实就是用来获取/操作DOM元素的;类似于jquey中的(“.xxx”);
缓存问题
ref 需要在dom渲染完成后才会有,在使用的时候确保dom已经渲染完成。比如在生命周期 mounted(){} 钩子中调用,或者在 this.$nextTick(()=>{}) 中调用。
组件内写法
filters:{
filter:function(data,arg1,arg2){
return ....
}
}
1.在html中使用
{{
msg |
filter(
‘arg1’,
‘arg2’) }}
2.methods中使用,并传参
methods:{
fn(){
let filter = this.$options.filters['filter']
let data = filter(this.msg,arg1,arg2)
}
}
3.在v-html中使用filters
<p><v-html="$options.filters.filter(this.msg,arg1,arg2)"></p>
Directive:指令
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换,不用在效验必选项
v-show是通过css的display:none进行隐藏控制,所以一开始就会渲染,肯定能够取到元素
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
三、自定义指令
组件:一般是指一个独立实体,组件之间的关系通常都是树状。
Vue``指令:用以改写某个组件的默认行为,或者增强使其获得额外功能,一般来说可以在同一个组件上叠加若干个指令,使其获得多种功能。比如 v-if,它可以安装或者卸载组件。
Vue 指令生命周期
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
生命周期函数中的参数
el: 指令所绑定的元素,可以用来直接操作 DOM,就是放置指令的那个元素。
binding: 一个对象,里面包含了几个属性
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
这样,任何页面或组件,只要通过 inject 注入 app 后,就可以直接访问 userInfo 的数据了,比如:
四、mixins基础概况
vue中的解释是这样的,如果觉得语言枯燥的可以自行跳过嘿~
混入 (mixins): 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
总结
vuex:用来做状态管理的,里面定义的变量在每个组件中均可以使用和修改,在任一组件中修改此变量的值之后,其他组件中此变量的值也会随之修改。
Mixins:可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值的修改在组件中不会相互影响。
与公共组件的区别
组件:在父组件中引入组件,相当于在父组件中给出一片独立的空间供子组件使用,然后根据props来传值,但本质上两者是相对独立的。
Mixins:则是在引入组件之后与组件中的对象和方法进行合并,相当于扩展了父组件的对象与方法,可以理解为形成了一个新的组件。
利用本地化缓存机制
这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护;
通过window.localStorage.getItem(key) 获取数据; 通过window.localStorage.setItem(key,value) 存储数据;
注意用JSON.parse() / JSON.stringify() 做数据格式转换;
五、修饰符
vue中的修饰符主要分为两类:
1.事件修饰符:
.stop 阻止单机事件冒泡
.prevent 阻止默认行为(比如 @submit.prevent 会阻止提交后刷新页面)(类似a标签javascript:void(0))
.capture 添加事件侦听器时使用捕获模式
.self 只有事件在元素本身(而不是子元素)触发时触发回调
.once 只触发一次(组件也适用)
.key 触发事件的按键
修饰符可以串联
.native
现在在组件上使用 v-on
只会监听自定义事件 (组件用 $emit
触发的事件)。如果要监听根元素的原生事件,可以使用 .native
修饰符
就是在父组件中给子组件绑定一个原生的事件,就将子组件变成了普通的HTML标签,不加’. native’事件是无法触 发的。
@keyup.enter.native
2.v-model 修饰符:
.lazy
在各种情况下,v-model
在input
事件中同步输入框的值与数据,但你可以添加一个修饰符lazy
,从而转变为在change
事件中同步:
.number
如果想自动将用户的输入值转换为Number类型(如果原值的转换结果为NaN则返回原值),可以添加一个修饰符number
给v-model
来处理输入值:
<input v-model.number="age" type="number">
这通常很有用,因为在type="number"
时HTML中输入的值也总是会返回字符串类型。
.trim
如果要自动过滤用户输入的首尾空格,可以添加trim
修饰符到v-model
上过滤输入:
插槽
除非子组件模板包含至少一个插口,否则父组件的内容将被替换。当子组件模板只有一个没有属性的slot时,父组件整个内容片段将插入到slot所在的DOM位置,并替换掉slot标签本身。
最初在标签中的任何内容都被替换为内容。备用内容在子组件的作用域内编译,并且仅在容纳元素为空,且没有要插入的内容时才显示备用内容。
假定my-component组件有下面模板:
<div>
<h2>我是子组件的标题</h2>
<slot>
只有在没有要分发的内容时才会显示。
</slot>
</div>
父组件模版:
<div>
<h1>我是父组件的标题</h1>
<my-component>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</my-component>
</div>
渲染结果:
<div>
<h1>我是父组件的标题</h1>
<div>
### 最后
**文章到这里就结束了,如果觉得对你有帮助可以点个赞哦**
**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**
![](https://img-blog.csdnimg.cn/img_convert/2addac01f045ee0c29e9b585a563be85.webp?x-oss-process=image/format,png)
有下面模板:
我是子组件的标题
只有在没有要分发的内容时才会显示。
```父组件模版:
<div>
<h1>我是父组件的标题</h1>
<my-component>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</my-component>
</div>
渲染结果:
<div>
<h1>我是父组件的标题</h1>
<div>
### 最后
**文章到这里就结束了,如果觉得对你有帮助可以点个赞哦**
**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**
[外链图片转存中...(img-NNYPowzO-1714367291543)]