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})
目录
相关文章
|
3天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发
|
3天前
|
存储 JavaScript
Vue 状态管理工具vuex
Vue 状态管理工具vuex
|
9天前
|
缓存 JavaScript UED
Vue 中实现组件的懒加载
【10月更文挑战第23天】组件的懒加载是 Vue 应用中提高性能的重要手段之一。通过合理运用动态导入、路由配置等方式,可以实现组件的按需加载,减少资源浪费,提高应用的响应速度和用户体验。在实际应用中,需要根据具体情况选择合适的懒加载方式,并结合性能优化的其他措施,以打造更高效、更优质的 Vue 应用。
|
8天前
|
JavaScript
如何在 Vue 中使用具名插槽
【10月更文挑战第25天】通过使用具名插槽,你可以更好地组织和定制组件的模板结构,使组件更具灵活性和可复用性。同时,具名插槽也有助于提高代码的可读性和可维护性。
13 2
|
8天前
|
JavaScript
Vue 中的插槽
【10月更文挑战第25天】插槽的使用可以大大提高组件的复用性和灵活性,使你能够根据具体需求在组件中插入不同的内容,同时保持组件的结构和样式的一致性。
12 2
|
8天前
|
前端开发 JavaScript 容器
在 vite+vue 中使用@originjs/vite-plugin-federation 模块联邦
【10月更文挑战第25天】模块联邦是一种强大的技术,它允许将不同的微前端模块组合在一起,形成一个统一的应用。在 vite+vue 项目中,使用@originjs/vite-plugin-federation 模块联邦可以实现高效的模块共享和组合。通过本文的介绍,相信你已经了解了如何在 vite+vue 项目中使用@originjs/vite-plugin-federation 模块联邦,包括安装、配置和使用等方面。在实际开发中,你可以根据自己的需求和项目的特点,灵活地使用模块联邦,提高项目的可维护性和扩展性。
|
9天前
|
JavaScript 前端开发 UED
vue 提高 tree shaking 的效果
【10月更文挑战第23天】提高 Vue 中 Tree shaking 的效果需要综合考虑多个因素,包括模块的导出和引用方式、打包工具配置、代码结构等。通过不断地优化和调整,可以最大限度地发挥 Tree shaking 的优势,为 Vue 项目带来更好的性能和用户体验。
|
9天前
|
缓存 JavaScript UED
Vue 中异步加载模块的方式
【10月更文挑战第23天】这些异步加载模块的方式各有特点和适用场景,可以根据项目的需求和架构选择合适的方法来实现模块的异步加载,以提高应用的性能和用户体验
|
9天前
|
JavaScript 测试技术 UED
解决 Vue 项目中 Tree shaking 无法去除某些模块
【10月更文挑战第23天】解决 Vue 项目中 Tree shaking 无法去除某些模块的问题需要综合考虑多种因素,通过仔细分析、排查和优化,逐步提高 Tree shaking 的效果,为项目带来更好的性能和用户体验。同时,持续关注和学习相关技术的发展,不断探索新的解决方案,以适应不断变化的项目需求。
|
10天前
|
JavaScript 搜索推荐 前端开发
Vue SSR 预渲染的广泛应用场景及其优势
【10月更文挑战第23天】Vue SSR 预渲染技术在众多领域都有着广泛的应用价值,可以显著提升网站的性能、用户体验和搜索引擎优化效果。随着技术的不断发展和完善,其应用场景还将不断拓展和深化
25 2