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-for 循环v-if 判断是否成立,它不成立代码不加入v-show 是否显示,显示后display为block,如果后面不成立变为nonev-bind 绑定变量 简写:v-on 事件 简写@v-else 如果v-if不成立,这个就成立v-else-if 再次判断v-model 绑定一个变量和当前表单的值绑定v-html 解析标签v-text 不解析标签v-once 只运行一次v-slot 插槽v-pre 不解析标签包裹中的{{变量}},这个变量不解析v-cloak 防止闪烁,在生命周期mounted前,变量在标签内无实际数据,这个可以防止在未有数据之前显示,而是有了数据后再显示出来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转成真实dommounted
数据改变时触发,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与相应的处理程序之间的映射关系
根据不同的url地址展示不同的内容或者页面因为vue是个spa(单页面应用,只有一个html文件)
监听hashchange事件vue-router
vue路由有哪几种模式,有什么区别
三种 hash模式(hashchange事件) 他带#号,用起来比较好用,比较丑 history模式(html5实现) 不带#号,比较好看,需要后端配合 abstract 在 Weex 环境中使用什么是嵌套路由,动态路由和路由重定向 嵌套路由:如果一个页面内点击跳到下一个地址,但是页面没有进行跳转,那么这个跳转的路由写在当前路由下,作为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
mutationsactionsgettersmodule每个部分都做什么
状态的流向(流程图)
辅助函数 辅助函数: …mapState(), 括号内可以写数组或者对象,写数组的话,名字无法改变,对象的话名字可以自己写;写在computed里面 辅助函数: …mapMutations(), 写在methods里面 辅助函数: …mapActions(), 写在methods里面 辅助函数: …mapGetters(), 写在computed里面
组件传参怎么做
父子传参非父子传参 父子组件之间的传参父传子:
父组件用自定义的属性 子组件用props去接受 props: [‘msg’] this.msg子传父
父组件用自定义事件,在父组件的template里写子组件 <child @message=“method”> method (val) { console.log(val) }子组件用emit去发布 this.emit(‘message’, 传递的值),这个会自动激发父组件写的自定义事件你常用的git命令有哪些
init 初始化config 配置 git config --global user.name ‘用户名’ git config --global user.email ‘邮箱’add 提交到暂存区commit 提交到本地仓库push 上传到远程仓库pull 从远程仓库获取git log --graph --pretty=oneline 查看分支记录branch 查看分支 如果加个分支名就会创建一个分支 ; branch -a 查看远程分支fetch --all 获取远程分支名称到本地checkout 切换分支 ; checkout -b 分支名 这样就会创建并且切换merge 合并分支clone + 地址 克隆一个与远程仓库有关联的文件夹status 查看git的状态reset HEAD^ 回退一个版本git reset --hard 版本id 回退到指定版本remote add origin +地址 与远程仓库创建联系git diff 查看版本的差别如果前端已经开发完成了,后端接口还没有给到,你是怎么做的
使用mock数据 采用fetchmock创建线上接口TypeScript
typescript它不是一门新的语言,它是一门用来规范js的语言
js依旧是一门弱类型的语言
ts是js的一个超集,广义的js是es,dom,bom,ts是es的超集
比方说强类型,面对对象的开发体系
ts常用在大型项目中,使得代码更加规范,协作更加友好,维护更加方便
特点:
增加了静态类型检查,增加了代码的健壮性 是编写时报错,js是执行时报错 使得重构更加的安全与便捷 多人协作的时候,提高生产力,降低维护成本常用的类型
string, number, boolean, any, void, never, Array<string> / string[], 枚举, 元组 string | number, interface在vue里面使用ts
类组件,扩展组件, 函数组件 修饰器服务端渲染
优势:
更好的SEO 搜索引擎优化 更快的到达时间劣势:
更高的开发要求 更高的服务器的要求nuxt.js
vue响应式原理
vue是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的getter,setter,当属性发生改变的时候,将变动发布给订阅者,触发监听回调
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化
vue3.0使用了proxy
浏览器的渲染原理和流程
浏览器将获取的HTML文档解析成DOM Tree(DOM树)。将CSS样式表,解析成CSSOM Tree(CSS树)。将DOM和CSSOM合并为渲染树(rendering tree),attachment渲染树的每个元素经过精确的计算后,给出坐标,laylout。将渲染树的各个节点绘制到屏幕上,painting。为什么要使用虚拟DOM
虚拟DOM是为了解决浏览器性能问题而被设计出来的。比如有10次循环,虚拟DOM不会立即操作DOM,而是将10次的diff内容保存在一个js对象里面,然后一次性的操作,避免大量无谓的计算操作内存中的js对象的速度显然更快,等更新完后,再将最终的js对象映射成真实的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() } }}