上篇讲到了Vue中的一些基础知识,本篇仍是一些基础知识,将Vue中一些特色点梳理一下。
目录
数据代理
Vue中的特色就是数据代理。
数据代理:通过一个对象代理另一个对象中的属性的操作(读 / 写 )
在vue中所有的对象属性都是通过数据代理管理的。而每一个对象属性都有与之对应的getter和setter,可以实现页面响应式渲染,即用户修改了数据就会重新读取并渲染页面。
数据代理的底层实现是通过 Object.defineProperty()给 vm 添加与 data 对象的属性对应的属性描述符。
计算属性computed
计算属性:要用的属性不存在,要通过已有属性来计算
例如当我们想要分别采集一个人的姓和名,然后在页面上显示这个人的姓名。我们就可以通过计算已有的姓属性和名属性,再通过计算属性计算姓名。当用户修改任一一项时,姓名都会发生改变。
该例子的完成方式有很多,例如用模板拼出来其实也可以实现。但是在模板里面写的话,不仅需要在最初初始化时就得把数据写上去,还会在用户修改时反复调用,效率并不高。
计算属性的底层实现还是借助了Object.defineProperty方法提供的getter和setter。且get会在最初执行一次,在依赖的数据被修改时会再次被调用。
优势:内部有缓存机制(复用),效率更高,方便调试
侦听属性watch(监听属性)
定义:当监视的属性变化时,回调函数自动调用,进行相关操作
注意:监视的属性必须存在,才能进行监视。
使用侦听属性也能实现上面的例子。监听的函数会接收两个参数,第一个参数是最新的值,第二个参数是输入之前的值。而配置项中有handler、immediate和deep三个参数。
handler:处理监听时变动的函数
immediate:组件加载立即触发回调函数执行,
deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用
优势:支持异步。
computed和watch对比:
| computed | watch | |
|---|---|---|
| 对象 | 需要属性不存在,通过存在的属性计算得出 | 存在的属性 |
| 是否支持缓存 | 支持缓存 | 不支持缓存 |
| 是否支持异步任务 | 不支持 | 支持 |
| 依赖其他属性 | 多对一或一对一 | 一对多 |
注意:computed能完成的功能,watch都可以完成,而watch能完成的computed不一定能完成!!
过滤器
过滤器:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
当我们想要过滤掉一些数据,或者对数据做一些简单的处理,我们就可以使用过滤器完成。
注册过滤器:
第一种:Vue.filter(name,callback)
第二种:new Vue{filters:{}}
使用过滤器:
第一种:{{ xxx | 过滤器名}}
第二种:v-bind:属性 = “xxx | 过滤器名”
注意:
1.多个过滤器可以串联使用。
2.过滤器没有改变原本的数据,是产生新的对应的数据
3.可以定义局部过滤器和全局过滤器
监视数据
1.监视数据的原理
Vue会监视data中所有层次的数据。
2.如何检测对象中的数据?
通过setter(会生成set方法)实现监视,且要在new Vue时就传入要监测的数据(定义vue的data时定义好,vue就会自动把所有属性的set方法生成)。
对象中后追加的属性,vue默认不做响应式处理(响应式处理即:即时响应数据到页面)
如需给后添加的属性做响应式(对象添加属性),请使用如下api:
Vue.set(targer,propertyName/index,value)
vue的实例对象.$set(targer,propertyName/index,value)
( 第一个参数表示要给哪个对象里面添加属性,第二个参数是添加的属性名或者数组的索引,第三个参数是添加的属性值)
3.如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事(即第四点里面的方法做了如下两件事):
(1)调用原生对应的方法对数组进行更新
(2)重新解析模板,进而更新页面
4.在vue修改数组中的某个元素一定要用如下方法
(1)使用这些api:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
(2)Vue.set()或者vue的实例对象.$set()
注意:不能给vue实例对象或者vm的根数据对象(_data)添加属性!
指令
前面介绍过在Vue中有两种将数据渲染到页面的方式:使用插值语法和指令语法。
来看看指令语法都有哪些吧。
| 指令 | 含义/作用 | 注意点 |
|---|---|---|
| v-bind | 单向绑定解析表达式 | 简写为 :xxx |
| v-model | 双向数据绑定 | 在表单中注意value值 |
| v-for | 遍历数据/对象/字符串 | |
| v-on | 绑定事件监听事件 | 可以简写为@ |
| v-if | 条件渲染(动态控制节点是否存在) | 元素在dom中动态生成 |
| v-else | 条件渲染(动态控制节点是否存在) | 与v-if连用,且结构不能打断 |
| v-show | 条件渲染(动态控制节点是否存在) | 元素在dom中存在 |
| v-text | 向其所在的节点中渲染文本内容 | 会替换节点中的内容 |
| v-html | 向指定节点中渲染包含html结构的内容 | 会替换掉节点中的所有内容,可以识别html内容 |
| v-cloak | 特殊属性,在Vue实例创建完毕并接管内容后,删除v-clock属性 | 没有值 |
| v-once | 所在节点在初次动态渲染后,就视为静态内容了 | 以后更改的数据不会影响该节点,优化性能 |
| v-pre | 跳过其所在节点的编译过程 | 可以跳过:没有使用指定语法、没有使用插值语法的节点、加快编译 |
注意:
1.v-html有安全性问题:
在网页上动态渲染html是非常危险的,容易导致xss攻击
一定要在可信的内容上使用v-html,永远不要在用户提交的内容上!!
2.css配合v-cloak可以解决网速慢时页面展示出{{xx}}的问题
自定义指定
我们也可以自定义一些指令,提高工作效率。自定义指令也分为局部指令和全局指令。
局部指令:directives 配置项自定义属性
函数式(element,binding)
1.指令与元素成功绑定时(一上来)
2.指定所在的模板被重新解析时
对象式(能处理一些细节)
bind():指令与元素成功绑定时调用
inserted():指令所在元素被插入页面时使用
update():指令所在模板结构被重新解析时调用全局指令:Vue.directive(指令名,配置对象/回调函数)
注意:指令定义时不加v-,但是使用时要加v-;指令名是多个单词,要使用kebab-case命名方式,不要使用camelCase命名
本篇案例:
<body>
<div id="root">
<button @click="student.age++">年龄+1岁</button>
<button @click="addSex">添加性别属性,默认值:男</button>
<button @click="student.sex = '女'">修改性别</button>
<button @click=addFriend>在列表首位添加一个朋友</button>
<button @click="updataFistFriend">修改第一个朋友的名字为:张三</button>
<button @click="addHobby">添加一个爱好为:学习</button>
<button @click="updateHobby">修改第一个爱好为:睡觉</button>
<button @click="fitlterHobby">过滤掉爱好中的抽烟</button>
<button @click="getData">点击更新时间</button>
<!-- <h2>时间戳:{{date.time}}</h2> -->
<h2>现在是:{{date.time | timeFormater}}</h2>
<h2>现在是:{{date.time | timeFormater('YYYY-MM-DD')}}</h2>
<h2 :class="fz">姓名:{{student.name}}</h2>
<h2>年龄:{{student.age}}</h2>
<h2 v-if="student.sex">性别:{{student.sex}}</h2>
<h2 :class="color" @click="changecolor">爱好:</h2>
<ul>
<li v-for="(h, index) in student.hobby" :key="index" :class="color" @click="changecolor">
{{h}}
</li>
</ul>
<h2>朋友们:</h2>
<ul>
<li v-for="(f, index) in friends" :key="index">
{{f.name}} -- {{f.age}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: "#root",
data: {
student: {
name: "Tom",
age: 18,
hobby: ['抽烟', "喝酒", "烫头"]
},
friends: [
{ name: "jerry", age: 20 },
{ name: "tony", age: 19 }
],
fz: 'fz',
color: '',
date: {
}
},
methods: {
addSex() {
this.$set(this.student, "sex", "男")
},
addFriend() {
this.friends.unshift({ name: "bob", age: 21 })
},
updataFistFriend() {
this.friends[0].name = "张三" // friends中的name方法有getter和setter 可以这么修改
},
addHobby() {
this.student.hobby.push("学习")
},
updateHobby() {
// this.student.hobby.splice(0, 1, "开车")
Vue.set(this.student.hobby, 0, '睡觉')
},
fitlterHobby() {
this.student.hobby = this.student.hobby.filter((h) => {
return h !== '抽烟'
})
},
changecolor() {
const arr = ['red', 'blue', 'purple'];
this.color = arr[Math.floor(Math.random() * 3)]
},
getData() {
const time = Date.parse(new Date());
this.$set(this.date, "time", time)
}
},
filters: {
timeFormater(value, str = 'YYYY年MM月DD日 HH:mm:ss') {
return dayjs(value).format(str)
}
}
})
</script>
</body>
本篇将Vue基础知识介绍的差不多啦,看完本篇都掌握的吗?

本文深入浅出地介绍了Vue.js中的数据代理、计算属性、侦听属性等核心概念,并对比了它们之间的区别与联系。此外,还讲解了过滤器、指令及数据监测等实用功能。
506

被折叠的 条评论
为什么被折叠?



