Vue学习笔记②

简介: Vue学习笔记②

计算属性

计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。

此处fullname调用了四次,但是1只执行了一次。get的作用:当fullName被读取的时候时,get就会被调用,且返回值就作为fullName的值。

计算属性的结果会被缓存,除非依赖的响应式 property 变化才会重新计算。注意,如果某个依赖 (比如非响应式 property) 在该实例范畴之外,则计算属性是不会被更新的。

get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<divid="root"style="margin: 121px 366px;">
        姓氏<inputtype="text"v-model="firstname"><br/>
<inputtype="text"v-model="nextname"><br/>
        姓名:<span>{{fullname}}</span><br/>
        姓名:<span>{{fullname}}</span><br/>
        姓名:<span>{{fullname}}</span><br/>
        姓名:<span>{{fullname}}</span><br/>
</div>
<script>
        Vue.config.productionTip= false
const vm = new Vue({
el:'#root',
data:{
firstname:'张',
nextname:'三'
        },
computed:{
fullname:{
get(){
console.log(1)
returnthis.firstname + this.nextname
                }
            }
        }
        })
</script>

  • 定义:要用的属性不存在,要通过已有属性计算得来。
  • 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
  • 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
  • 备注:
    计算属性最终会出现在vm上,直接读取使用即可。
    如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
  • 简写

    PLAINTEXT
1
2
3
4
5
computed:{
    fullname(){
    return this.firstname + this.nextname
    }
}

监视 属性

  1. 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
  2. 监视的属性必须存在,才能进行监视!!
  3. 监视的两种写法:
  • new Vue时传入watch配置
  • 通过vm.$watch监视,传两个参数,一个属性,一个方法('isHot',{handler(){}})

写法一:

JS

1
2
3
4
5
6
7
8
watch:{
isHot:{
immediate:true, //初始化时让handler调用一下
handler(newvalue,oldvalue){
console.log("isHot被更改了",newvalue,oldvalue) 
        }
    }
}

写法二:

JS

1
2
3
4
5
6
7
8
vm.$watch('isHot',
    {
immediate:true,
handler(newvalue){
console.log("isHot被更改啦",newvalue);
        }
    }
)

深度监视

  1. Vue中的watch默认不监测对象内部值的改变(一层)。
  2. 配置deep:true可以监测对象内部值改变(多层)。

备注:

(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!

(2).使用watch时根据数据的具体结构,决定是否采用深度监视。

(3).deep默认为false为了提高开发效率,

JS

1
2
3
4
5
6
7
8
9
vm.$watch('number',
    {
immediate:true,
handler(newvalue){
console.log("number被更改啦",newvalue);
        },
deep:true
    }
)

简写

简写的话,不能够添加deep,immediate属性。

简写一:

JS

1
2
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)

简写二:

JS

1
2
3
vm.$watch('isHot',function(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
		})

计算属性和监测属性对比

如下代码证明watch能执行异步操作,但是computed不行,setTimeout必须是箭头函数,this指向所定义的作用域内的Vue实例对象,setTimeout下的回调函数不是Vue实例对象调用的,而是V8浏览器的js引擎调用的,所以不使用箭头函数的话,this指向window。

JS

1
2
3
4
5
6
7
8
9
10
11
watch:{
firstName(val){
setTimeout(()=>{
console.log(this)
this.fullName = val + '-' + this.lastName
		},1000);
	},
lastName(val){
this.fullName = this.firstName + '-' + val
	}
}

computed和watch之间的区别:

  1. computed能完成的功能,watch都可以完成。
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

两个重要的小原则:

  1. 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
  2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数这些都是异异步的),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。

绑定class样式

写法:class=”xxx” xxx可以是字符串、对象、数组。

字符串写法适用于:类名不确定,要动态获取。

对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。

数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

HTML

1
2
3
4
5
6
7
8
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 ,比如mood确定但是mood的值是normal,happy,sad不确定-->
<divclass="basic":class="mood" @click="changeMood">{{name}}</div><br/><br/>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<divclass="basic":class="classArr">{{name}}</div><br/><br/>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<divclass="basic":class="classObj">{{name}}</div><br/><br/>

绑定style样式

:style=”{fontSize: xxx}”其中xxx是动态值。

:style=”[a,b]”其中a、b是样式对象。

PLAINTEXT

1
2
3
4
5
6
7
8
9
data:{
   showin:{
        backgroundColor:'orange',
        fontSize: '50px',
        margin:'auto',
        textAlign:'center'
}
},

条件渲染

HTML

1
2
3
4
5
6
7
8
9
10
<divid="root">
<h2>hello,{{n}}</h2>
<button @click="n++">anniu</button>
<divv-if="n===1">a</div>
<divv-else-if="n===2">b</div>
<divv-else-if="n===3"> c</div>
<!-- <div v-show="n===1">a</div>
  <div v-show="n===2">b</div>
  <div v-show="n===3">c</div> -->
</div>

v-if

写法:

(1).v-if=”表达式”

(2).v-else-if=”表达式”

(3).v-else,else后面无需跟条件。

适用于:切换频率较低的场景。

特点:不展示的DOM元素直接被移除

注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

v-show

写法:v-show=”表达式”

适用于:切换频率较高的场景。

特点:不展示的DOM元素不会被移除,vue内部添加style="display :none",仅仅是使用样式隐藏掉

3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

列表渲染

1.用于展示列表数据

2.语法:v-for=”(item, index) in xxx” :key=”yyy”

遍历数组:p是数组中的每个数据,index是当前索引(用的最多的一种)。

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<divid="root">
<ul>
<liv-for="(p,index) in persons":key="p.id">
            {{p.name}}-{{p.age}}
</li>
</ul>
</div>
<script>
new Vue({
el:'#root',
data:{
persons:[
            {id:'01',name:'张三',age:'18'},{
id:'02',name:'李四',age:'20'
            },{
id:'03',name:'王五',age:'18'
            }
        ]
     }
 })
</script>

遍历对象:value是值,k是属性

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ul>
<liv-for="(value,k) of car":key="k">
			{{k}}-{{value}}
</li>
</ul>
<scripttype="text/javascript">
	Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
car:{
name:'奥迪A8',
price:'70万',
color:'黑色'
			},
str:'hello'
		}
	})
</script>

Key的作用和原理

  • 虚拟DOM中key的作用:
    变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
    随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
  • 对比规则:

(1).旧虚拟DOM中找到了与新虚拟DOM相同的key

①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!

②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

(2).旧虚拟DOM中未找到与新虚拟DOM相同的key,创建新的真实DOM,随后渲染到到页面。

  • 用index作为key可能会引发的问题:
    破坏顺序操作:
    会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低,逆序操作重新生成张三李四王五。

如果结构中还包含输入类的DOM:

会产生错误DOM更新 ==> 界面有问题。

开发中如何选择key?:

1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。

2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,

使用index作为key是没有问题的。

列表过滤

watch监测属性实现

  1. 创建persons属性,创建一个filterper数组为了避免更改原来的数据。
  2. 添加watch属性,返回this.filterper的值,因为空字符串也是包含在字符串中,使用immediate:true让数据能够全部显示。

  3. this.filterper= this.persons.filter((p)=>{return p.name.indexOf(val)!== -1}) ,即是用arr.filter()的回调判断arr.indexOf()的返回值如果为-1就不存在。

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<divid="root">
<ul>
<inputtype="text"v-model="keywords">
<liv-for="(p,index) in filterper":key="p.id">
                {{p.name}}-{{p.age}}
</li>
</ul>
</div>
<script>
new Vue({
el:'#root',
data:{
persons:[
            {id:'001',name:'马冬梅',age:19,sex:'女'},
						{id:'002',name:'周冬雨',age:20,sex:'女'},
						{id:'003',name:'周杰伦',age:21,sex:'男'},
						{id:'004',name:'温兆伦',age:22,sex:'男'}
            ],
keywords:'',
filterper:[]
         },
watch:{
keywords:{
immediate:true,
handler(val){
this.filterper= this.persons.filter((p)=>{
return p.name.indexOf(val)!== -1
                   })
                }
             }
         }
     })
</script>

computed计算属性实现

  1. 第一个return是计算属性的返回值,第二个return是filter回调函数的返回值。

JS

1
2
3
4
5
6
7
computed:{
filPerons(){
returnthis.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
		})
	}
}

列表排序

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    computed:{
filterpers(){
const arr=  this.persons.filter((p)=>{
return p.name.indexOf(this.keywords) !== -1
		})
if(this.sorttype){
                         arr.sort((a,b)=>{
returnthis.sorttype=== 1 ?  a.age -b.age :b.age -a.age
                        })
                    }
return arr
	}
}

Vue监听数据原理

对象

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 核心数据响应式方法
functiondefineReactive(obj,key,val){
// val可能还是个对象,需要递归一下
    objserve(val)
Object.defineProperty(obj,key,{
get(){
return val
        },
set(newVal){
if(newVal !== val){
                val = newVal
// 如果改变的是个对象,还需要调用一下
                objserve(newVal)
console.log('set', newVal);
// 在这里已经监听到了数据的变化,后续可以做一些更新视图的操作
            }
        }
    })
}
// 如果一个对象有多个属性,循环调用defineReactive,传入每一个值去进行监听
functionobjserve(obj){
// 判断obj类型
if(Object.prototype.toString.call(obj)!=="[object Object]"){
return
    }
Object.keys(obj).forEach(key =>defineReactive(obj,key,obj[key]))
}
// 如果给对象增加新的属性,是监听不到变化的,那么需要用set方法传入新对象,调用defineReactive手动监听一下
functionset(obj,key,val){
    defineReactive(obj,key,val)
}
const obj = {foo:'foo',baz:{a:1}};
objserve(obj)
obj.foo = '2222'
obj.baz.a = '3333'
obj.baz = {a:10} 
obj.baz.a = 100
set(obj,"dong",'dong')
obj.dong = "dong1"

数组

变更方法

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

你可以打开控制台,然后对前面例子的 items 数组尝试调用变更方法。比如 example1.items.push({ message: 'Baz' })

Vue.set()

Vue.set( target, propertyName/index, value )

  • 参数
  • {Object | Array} target
  • {string | number} propertyName/index
  • {any} value
  • 返回值:设置的值。
  • 用法
    向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi')

注意对象不能是 Vue 实例,或者 Vue 实例的根数据对象。

只能在data的对象中添加Vue.set(),而不能在data上直接添加,也就是不能在vm和vm._data上添加。

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const vm = new Vue({
el:'#root',
data:{
school:{
name:'尚硅谷',
address:'北京',
			},
student:{
name:'tom',
age:{
rAge:40,
sAge:29,
				},
friends:[
					{name:'jerry',age:35},
					{name:'tony',age:36}
				]
			}
		},
methods: {
addSex(){
// Vue.set(this.student,'sex','男')
this.$set(this.student,'sex','男')
			}
		}
	})

总结

Vue监视数据的原理:

\1. vue会监视data中所有层次的数据。

\2. 如何监测对象中的数据?

通过setter实现监视,且要在new Vue时就传入要监测的数据。

(1).对象中后追加的属性,Vue默认不做响应式处理

(2).如需给后添加的属性做响应式,请使用如下API:

Vue.set(target,propertyName/index,value) 或

vm.$set(target,propertyName/index,value)

\3. 如何监测数组中的数据?

通过包裹数组更新元素的方法实现,本质就是做了两件事:

(1).调用原生对应的方法对数组进行更新。

(2).重新解析模板,进而更新页面。

4.在Vue修改数组中的某个元素一定要用如下方法:

1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

2.Vue.set() 或 vm.$set()

特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
methods: {
	addSex(){
		// Vue.set(this.student,'sex','男')
		this.$set(this.student,'sex','男')
	},
	addFriend(){
		this.student.friends.unshift({name:'jack',age:70})
目录
相关文章
|
4月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
454 2
|
3月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
394 137
|
7月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
921 0
|
7月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
6月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
545 1
|
6月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
362 0
|
7月前
|
JavaScript 前端开发 开发者
Vue 自定义进度条组件封装及使用方法详解
这是一篇关于自定义进度条组件的使用指南和开发文档。文章详细介绍了如何在Vue项目中引入、注册并使用该组件,包括基础与高级示例。组件支持分段配置(如颜色、文本)、动画效果及超出进度提示等功能。同时提供了完整的代码实现,支持全局注册,并提出了优化建议,如主题支持、响应式设计等,帮助开发者更灵活地集成和定制进度条组件。资源链接已提供,适合前端开发者参考学习。
561 17
|
7月前
|
JavaScript 前端开发 UED
Vue 表情包输入组件实现代码及详细开发流程解析
这是一篇关于 Vue 表情包输入组件的使用方法与封装指南的文章。通过安装依赖、全局注册和局部使用,可以快速集成表情包功能到 Vue 项目中。文章还详细介绍了组件的封装实现、高级配置(如自定义表情列表、主题定制、动画效果和懒加载)以及完整集成示例。开发者可根据需求扩展功能,例如 GIF 搜索或自定义表情上传,提升用户体验。资源链接提供进一步学习材料。
379 1
|
7月前
|
存储 JavaScript 前端开发
如何高效实现 vue 文件批量下载及相关操作技巧
在Vue项目中,实现文件批量下载是常见需求。例如文档管理系统或图片库应用中,用户可能需要一次性下载多个文件。本文介绍了三种技术方案:1) 使用`file-saver`和`jszip`插件在前端打包文件为ZIP并下载;2) 借助后端接口完成文件压缩与传输;3) 使用`StreamSaver`解决大文件下载问题。同时,通过在线教育平台的实例详细说明了前后端的具体实现步骤,帮助开发者根据项目需求选择合适方案。
739 0
|
7月前
|
JavaScript 前端开发 UED
Vue 项目中如何自定义实用的进度条组件
本文介绍了如何使用Vue.js创建一个灵活多样的自定义进度条组件。该组件可接受进度段数据数组作为输入,动态渲染进度段,支持动画效果和内容展示。当进度超出总长时,超出部分将以红色填充。文章详细描述了组件的设计目标、实现步骤(包括props定义、宽度计算、模板渲染、动画处理及超出部分的显示),并提供了使用示例。通过此组件,开发者可根据项目需求灵活展示进度情况,优化用户体验。资源地址:[https://pan.quark.cn/s/35324205c62b](https://pan.quark.cn/s/35324205c62b)。
366 0