vue
vue中的事件修饰符
- prevent:阻止默认事件(常用)
- stop: 阻止事件冒泡(常用)
- once: 事件只触发一次(常用)
- capture:使用事件的捕获模式
- self : 只有event.target是当前操作的元素时才触发事件
- passive: 事件的默认行为立即执行
修饰符可以连续写:
<a href="#" @click.prevent.stop='onreset'></a>
computed
computed:{
//mock_ze_ren_machine是变量名(因为v-model双向绑定,没set会报错)
mock_ze_ren_machine: {
get() {
return this.stepsObj.checked3 && this.stepsObj.visible_mock_zeren;
},
set(v) {
this.stepsObj.visible_mock_zeren = v
}
},
}
methods vs computed
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值
。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。使用 computed 性能会更好
,但是如果你不希望缓存,你可以使用 methods 属性。
watch
异步数据
的加载 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。
watch:{
//每当stepsObj.checked3变化时,就调用handler函数
//使用字符串的形式,监听多级结构中某个属性的变化
"stepsObj.checked3": {
handler(newVal, oldVal) {
if(!oldVal && newVal){
this.stepsObj.visible_mock_zeren = true
}
},
immediate: true // 立即处理 进入页面就触发
},
}
监听不到对象属性的变化,需要使用深度监听deep
watch:{
stepsObj: {
handler(newVal, oldVal) {
if(!oldVal && newVal){
this.stepsObj.visible_mock_zeren = true
}
},
//监听多级结构中所有属性的变化
deep: true //表示是否深度监听,侦听器会一层层地向下遍历,给对象的每个属性都加上侦听器
},
}
深度监听:
- Vue中的watch默认不监听对象内部值的改变(一层)
- 配置deep: true可以监听对象内部值改变(多层)
备注:
- Vue自身可以监听对象内部值的改变,但Vue提供的watch默认不可以
- 使用watch时根据数据的具体结构,决定是否采用深度监听。
computed vs watch
- computed能完成的功能,watch都可以完成;
- watch能完成的功能,computed不一定能完成。例如:watch可以进行异步操作。
原则:
- 所有被vue管理的函数,最好写成
普通函数
,这样this的指向才是vm 或组件实例对象。 - 所有不被vue管理的函数(定时器的回调函数、ajax的回调函数等),最好
写成箭头函数
,这样this的指向才是vm 或组件实例对象。
样式绑定
v-bind 在处理 class 和 style 时, 表达式除了可以使用字符串
之外,还可以是对象或数组
。
v-bind:class 可以简写为 :class。:class 指令也可以与普通的 class 属性共存。
- 字符串写法,适用于:样式的类名不确定,需要动态指定。
<div class="basic" :class="mood" @click="handleMood"></div>
- 数组写法,适用于:要绑定的样式个数不确定,名字也不确定。
<div class="basic" :class="classArr" @click="handleMood"></div>
- 对象写法,适用于:要绑定的样式个数确定,名字也确定,但要动态决定要不要用。
<div class="basic" :class="classObj" @click="handleMood"></div>
:style绑定到一个样式对象
<div :style="styleObject">菜鸟教程</div>
v-if
条件判断使用 v-if 指令,指令的表达式
返回 true 时才会显示。因为 v-if 是一个指令,所以必须将它添加到一个元素上。如果是多个元素,可以包裹在<template>
元素上,并在上面使用 v-if。最终的渲染结果将不包含 <template>
元素。
<a-step title="人判" v-if="stepsObj.checked1 && stepsObj.checked2" >
<a-icon type="user" slot="icon"></a-icon>
<span slot="description">
<a-switch v-model="stepsObj.checked7" checked-children="mock责任" un-checked-children="无mock" />
</span>
</a-step>
v-else 、v-else-if 必须跟在 v-if 或者 v-else-if之后。
v-show
指令的表达式返回 true 时才会显示。
v-if vs v-show
不同的是有 v-show 的元素会始终渲染并保持在 DOM 中。v-show 是简单的切换元素的 CSS 属性 display
。
- v-if 是真实的条件渲染,因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件。
- v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——在条件第一次变为真时才开始局部编译(编译会被缓存起来)。
- 相比之下, v-show 简单得多——元素始终被编译并保留,只是简单地基于 CSS 切换。
一般来说, v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗
。因此,如果需要频繁切换使用 v-show 较好,如果在运行时条件不大可能改变则使用 v-if 较好。
v-for
用 v-for 指令根据一组数组的选项列表进行渲染。 v-for 指令需要以 item in items 形式的特殊语法, items 是源数据数组并且 item 是数组元素迭代的别名。
<a-space>
<a-select style="width: 100px" v-model="tag_l1" @change="handleTagsChange">
<a-select-option v-for="item in tag_res" :key="item.value" :value="item.value" :label="item.desc">{{item.desc}}</a-select-option>
</a-select>
<a-select v-model="tag_l2" style="width: 180px">
<a-select-option v-for="child in children" :key="child.value" :value="child.value" :label="child.desc">{{child.desc}}</a-select-option>
</a-select>
</a-space>
handleTagsChange(value) {
for (let i=0,len=tag_res.length; i<len; i++)
{
if(tag_res[i]['value'] == value){
this.children = tag_res[i]["children"]
this.tag_l2 = this.children[0]['value']
break
}
}
},
v-for 还支持一个可选的第二个参数为当前项的索引。
可以用 of 替代 in
作为分隔符;
在遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }} : {{ value }}
</div>
v-for 也可以取整数
<div>
<span v-for="n in 10">{{ n }}</span>
</div>
//结果[1,10]
vue中key的作用与原理
1、虚拟DOM中key的作用
key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2、比较规则:
1)旧虚拟DOM中找到了与新虚拟DOM相同的key
- 若虚拟DOM中的内容没变,直接使用之前的真实DOM
- 若虚拟DOM中的内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
2)旧虚拟DOM中未找到与新虚拟DOM相同的key
- 创建新的真实DOM,随后渲染到页面
3、用index作为key可能会引发的问题
1)若对数据进行:逆序添加、逆序删除等破坏顺序操作
- 会产生没有必要的真实DOM更新 =>界面效果没问题,但效率低
2)如果结构中还包含输入类DOM
- 会产生错误类DOM更新 => 界面有问题
4、开发中如何选择key
- 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证、学号等唯一值
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作 ,仅用于渲染列表用于展示,使用index作为key是没有问题的。
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的根数据对象添加属性。
MVVM模型
1、M:模型(Model), 对应data中的数据
2、V:视图(View),对应模板代码template
3、VM:视图模型(ViewModel),Vue实例
Vue中的数据代理
Vue中的数据代理
通过vm对象来代理data对象中属性的操作(读/写)Vue中的数据代理的好处
方便操作data中的数据基本原理
通过Object.defineProperties()把data对象中所有属性添加到vm上
为每一个添加到vm上的属性,都指定一个getter/setter
在getter/setter内部去data中对应的属性
使用iframe内嵌子页面
src中的链接返回一个页面
<iframe title="666" src="https://xxxx" width="1000" height="380" frameborder="0" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe>
iframe带参数
<iframe title="666" :src=url width="1000" height="380" frameborder="0" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe>
this.url = `https://baidu.com/aaa/${this.bbbb_key}?taskId=${this.ccc_key}`
Object.assign
通过
this.$data
获取当前状态下的data,通过this.$options.data()
获取该组件初始状态下的data
//Object.assign(this.$data, this.$options.data()) // 这里重置 data 下的所有数据
Object.assign(this.$data.stepsObj, this.$options.data().stepsObj) // 这里重置 stepsObj 数据,其他不受影响
Vue中有2种数据绑定的方式
v-bind 单向绑定: 数据只能从data流向页面。
v-model双向绑定: 数据可从data流向页面,也可以从页面流向data;
- 用来在 input、select、textarea、checkbox、radio等
表单控件元素上
创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。
Vue模版语法有2大类
- 插值语法: 用于解析
标签体
内容
- {{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
- 指令语法:
- 功能:用于解析标签(包括: 标签属性、标签体内容、绑定事件……)
- 举例::href=“xxx”, xxx同样是js表达式,且可以直接读取到data中的所有属性
- 指令:v-bind,单向绑定解析表达式,可简写为 :xxx
v-model,双向数据绑定
v-for, 遍历数组/对象/字符串
v-on,绑定事件监听,可简写为@
v-if,条件渲染(动态控制节点是否存在)
v-else,条件渲染(动态控制节点是否存在)
v-show,条件渲染(动态控制节点是否展示)
Vue生命周期
将要创建 => 调用beforeCreate(){} 函数,
创建完毕 => 调用created(){}函数,
将要挂载 => 调用beforeMount() {},
挂载完毕 => 调用mounted() {}函数,
将要更新 => 调用beforeUpdate() {}函数,
更新完毕 => 调用updated() {}函数,
将要销毁 => 调用beforeDestroy() {}函数,
销毁完毕 => 调用destroyed() {}函数,
常用的生命周期钩子:
- mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】;
- beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
关于销毁Vue实例:
- 销毁后借助vue开发者工具看不到任何信息
- 销毁后自定义事件会失效,但原生DOM事件依然有效。
- 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会触发更新流程了。
配置项props
功能:让组件接收外部传过来的数据。
1)传递数据:
<Demo name="xxx" />
- 接收数据:
第一种方式(只接收)
props: ['name']
第二种方式(限制类型)
props: {
name:Number
}
第三种方式(限制类型、必要性,指定默认值)
props: {
name:{
type: String, //类型
required: true, //必要性
default:'老王' //默认值
}
}
⚠️props是只读的,Vue底层会监测你对props,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
ref属性
1、被用来给元素或子组件注册引用信息(id的替代者)
2、应用在html标签上获取的是真实的DOM元素,应用在组件标签上是组件实例对象
3、使用方式:
打标示:
<h1 ref="xxx"> ……</h1> 或 <Demo ref="xxx"></Demo>
获取:this.$ref.xxx
组件通信
全局事件总线
src/main.js
new Vue({
router,
store,
i18n,
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this //全局事件总线
}
}).$mount('#app')
$emit子组件调用父组件的方法并传递数据
发布订阅
代理
插槽
- 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件->子组件。
- 分类:默认插槽、具名插槽、作用域插槽
- 使用方式:
默认插槽:
父组件:
<Category>
<div>html结构</div>
</Category>
子组件:
<template>
<div>
<!--定义插槽 -->
<slot>插槽默认内容...</slot>
</div>
</template>
具名插槽:可使用slot="xxx" 或v-slot:=xxx(不要引号)
父组件:
<Category>
<template slot="center">
<div>html结构1</div>
</template>
<template v-slot:=footer>
<div>html结构2</div>
</template>
</Category>
子组件:
<template>
<div>
<!--定义插槽 -->
<slot name="center">插槽默认内容...</slot>
<slot name="footer">插槽默认内容...</slot>
</div>
</template>
作用域插槽:
数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。
可使用scope或者slot-scope
父组件:
<Category>
<template scope="scopeData">
<!--生成的是ul列表 -->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
<Category>
<template slot-scope="scopeData">
<!--生成的h4 -->
<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
</template>
</Category>
子组件:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name: "Category",
props:["title"],
data() {
return {
games:[]
}
}
</script>