指令、插值、动态属性
- 插值表达式
- 指令、动态属性
- v-html:会有xss风险,会覆盖子组件
// 动态属性 class、style
<p :class="{black: isBlack, yellow: isYellow}"></p>
<p :class="[black, yellow]"></p>
<p :style="styleData"></p>
data() {
return {
isBlack: true,
isYellow: false,
black: 'black',
styleData: {
fontSize: '12px',
color: 'red'
}
}
}
computed、watch 和 method
- computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
- watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
watch: {
// 原始类型
name(oldVal, newVal) {}
// 引用类型
info: {
handler(val) {},
deep: true // 深度监听
}
}
- method:只要把方法用到模板上了,每次一变化就会重新渲染视图,性能开销大
v-show 与 v-if 有什么区别?
- v-if 如果条件不成立不会渲染当前指令所在节点的DOM元素
- v-show 只是切换当前DOM的显示与隐藏,display: none
所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
v-for、key
v-for 可以遍历数组也可以遍历对象
遍历数组:v-for="(item, index) in Arr" key="item.key"
遍历对象:v-for="(val, key, index) in Obj" key="key"
key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速
v-for 不要和 v-if 一起使用:v-for 优先级高点,先循环,后判断(多次判断渲染)
事件
event 是原生的
事件被挂载在当前节点
<p @click="handleClick1"></p> 不传参,接受参数就是event
<p @click="handleClick2('asd', $event)"></p> 传event就写$event
事件修饰符
- @click.stop:阻止单击事件继续传播(冒泡)
- @click.ctrl:即使 Alt 或 Shift 被一同按下时也会触发
v-model
修饰符
- v-model.trim
- v-model.number
- v-model.lazy
vue的生命周期(挂载、更新、销毁)
- beforeCreate:组件实例被创建之初,组件的属性生效之前
- created:组件实例已经完全创建,属性也绑定,但真实 dom 还没有生成,$el 还不可用
- beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用
- mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子
- beforeUpdate:组件数据更新之前调用,发生在虚拟 DOM 打补丁之前
- updated:组件数据更新之后
- beforeDestory:组件销毁前调用,自定义事件可以在这销毁,避免内存泄漏
- destoryed:组件销毁后调用
Vue 的父组件和子组件生命周期钩子函数执行顺序?
- 加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted - 子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated - 父组件更新过程
父 beforeUpdate -> 父 updated - 销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
为什么data是一个函数
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。
Vue 组件间通信有哪几种方式?
- 父子组件通信
props
/$emit
ref
与$parent / $children
- 兄弟组件通信
自定义事件 EventBus
定义$eventBus.on('事件名', 回调函数)
触发$eventBus.emit('事件名', 传参)
解绑$eventBus.off('事件名')
/**
* 全局单例消息通道
*/
import Vue from 'vue'
vue.$prototype.$eventBus = new Vue({
methods: {
emit(event, ...args) {
this.$emit(event, ...args)
},
on(event, callback) {
this.$on(event, callback)
},
once(event, callback) {
this.$once(event, callback)
},
off(event, callback) {
this.$off(event, callback)
},
},
})
- 隔代组件通信
$attrs/$listeners
provide / inject
说说你对 SPA 单页面的理解,它的优缺点分别是什么?
仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载
优点
- 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
- 基于上面一点,SPA 相对对服务器压力小;
- 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点
- 初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将JavaScript、CSS 统一加载,部分页面按需加载;
- 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
- SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。