mvc和mvvm
mvc和mvvm
都是软件架构思想
mvc (react)
model: 数据保存
view: 用户界面
Controller: 业务逻辑
所有通信都是单向的. view -> controller -> model -> view
mvvm(vue)
model: 数据层
view: 视图层
viewmodel: 视图模型层
view和viewmodel是同步更改的,viewmodel再和model层进行通信
数据流向 都是单向
mvc: view -> controller -> model -> view
mvvm: view <-> viewmodel -><- model
vue中常见的指令
v-if和v-show的区别和场景,v-html和v-text的区别
v-if和v-show
区别:
1.手段:v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏;
2.编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
3.编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载); v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
4.性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
场景:
如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好
v-html和v-text
v-text和{{}}表达式渲染数据,不解析标签。
v-html不仅可以渲染数据,而且可以解析标签。
vue生命周期
初始化事件,生命周期
beforeCreate
注入数据,初始化响应式数据
cteated
是否有el和template选项
beforeMount
将数据挂载到模板中,将虚拟DOM转成真实dom
mounted
数据改变时触发,dom的更新前后
beforeUpdate
updated
组件销毁的时候触发
beforeDestroy
destroyed
activated
缓存组件被激活时调用
deactivated
缓存组件被停用时调用
errorCaptured
子孙组件出错时调用
计算属性,方法,侦听器的区别
计算属性有缓存,方法无缓存,所以只有在数据发生变化的时候,计算属性才行重新执行
watch适合处理的场景是,侦听一个数的变化,当该数据变化,来处理其他与之相关数据的变化(该数据影响别的多个数据)
computed适合处理的场景是,获得一个值或者结果,该结果受其他的依赖的影响。(一个数据受多个数据影响)
描述一下插槽,过滤器和混入
Mixin混入:把各个组件下相同的js部分提取出来,分发给每一个用到的组件,这样可以减少代码量进行优化,但是分发到各个组件下的数据都是相互独立的 全局的mixin不需要在vue实例下进行mixins=[mixin] ,局部的要
//全局的mixin,不需要在实例vue里进行mixins=[mixin]
Vue.mixin({
methods: {
hand() {
console.log(1)
}
}
})
//局部
const mixin = {
data() {
return {
pageNum: 1,
pageCount: 10
}
},
created() {
console.log("mixin")
}
}
插槽:在子组件调用处的中间插入HTML的内容,叫做插槽
-具名插槽:在子组件分发插槽处,寻找父组件对应的插槽名字,把相应的HTML内容渲染到子组件中,注意HTML结构,如果不写名字,默认名字为default
-作用域插槽:子组件的数据传递给父组件时,使用作用域插槽
过滤:将传入的数据进行改变在输出
什么是前端路由,传统的路由实现?
一个url与相应的处理程序之间的映射关系
因为vue是个spa(单页面应用,只有一个html文件)
vue-router
vue路由有哪几种模式,有什么区别
什么是嵌套路由,动态路由和路由重定向
嵌套路由:如果一个页面内点击跳到下一个地址,但是页面没有进行跳转,那么这个跳转的路由写在当前路由下,作为child路由
动态路由:- 例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果
- 动态路径参数 以冒号开头
path: ‘/detail/:id’
路由重定向:redirect
重定向也是通过 routes 配置来完成,可以从一个url重定向到另一个url
{ path: '/', // redirect是重定向 redirect: '/index', },
- 路由传参怎么做?
const router = new VueRouter({ … })
router.beforeEach((to, from, next) => {
// …
})
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
router.afterEach((to, from) => {
// …
})
beforeEnter: (to, from, next) => {
// …
}
写在路由内部的
写在.vue文件里面,当作option使用
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 this
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 this
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 this
}
描述一下vuex(从下面几个方向回答)
是做什么的?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
有哪几个部分
-state
每个部分都做什么
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
辅助函数
辅助函数: …mapState(), 括号内可以写数组或者对象,写数组的话,名字无法改变,对象的话名字可以自己写;写在computed里面
辅助函数: …mapMutations(), 写在methods里面
辅助函数: …mapActions(), 写在methods里面
辅助函数: …mapGetters(), 写在computed里面
组件传参怎么做
父传子:
子传父
你常用的git命令有哪些
如果前端已经开发完成了,后端接口还没有给到,你是怎么做的
TypeScript
typescript它不是一门新的语言,它是一门用来规范js的语言
js依旧是一门弱类型的语言
ts是js的一个超集,广义的js是es,dom,bom,ts是es的超集
比方说强类型,面对对象的开发体系
ts常用在大型项目中,使得代码更加规范,协作更加友好,维护更加方便
特点:
增加了静态类型检查,增加了代码的健壮性
是编写时报错,js是执行时报错
使得重构更加的安全与便捷
多人协作的时候,提高生产力,降低维护成本
常用的类型
string, number, boolean, any, void, never, Array / string[], 枚举, 元组
string | number, interface
在vue里面使用ts
类组件,扩展组件, 函数组件
修饰器
服务端渲染
优势:
更好的SEO 搜索引擎优化
更快的到达时间
劣势:
更高的开发要求
更高的服务器的要求
nuxt.js
vue响应式原理
vue是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的getter,setter,当属性发生改变的时候,将变动发布给订阅者,触发监听回调
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化
vue3.0使用了proxy
浏览器的渲染原理和流程
为什么要使用虚拟DOM
diff操作
数据改变,虚拟DOM也会改变
我们不想重新渲染vdom,我们只想渲染改变的部分,就需要用到diff算法
两个树如果完全比较,时间复杂度是O(n^3),Vue的Diff算法的时间复杂度是O(n),意味着只能平层的比较两棵树的节点,放弃了深度遍历。似乎牺牲了一定的精准性来换取速度,但考虑到前端页面通常不会跨层移动DOM元素,这样做是优先的
采用了同级比较,只有count相同的children进行比较
比较他们的key,进行增加,删除,替换,换位等操作
自定义指令
全局定义:他也可以加修饰符,绑定元素的所有内容,全部在binding里,可以通过判断修饰符的内容进行一些操作
//写法一
Vue.directive(‘focus’, { //定义一个v-focus
// 当被绑定的元素插入到 DOM 中时……
inserted: function(el, binding) { //el指的是绑定的元素
// 聚焦元素
el.focus()
}
})
//全局的第二种写法
Vue.directive('focus', {
bind() {},//bind表示当前指令绑定到该元素身上,立刻触发
// inserted表示绑定的元素已经渲染为真实的dom,并且在页面中已经可以看到
inserted: function(el) {
// 聚焦元素
el.focus()
}
})
局部定义,只能在当前组件使用
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}