vue相关

1.vue的MVVM
MVVM 全称 model view view-model,是一种设计思想。
model层代表数据模型,可以在model层中定义数据修改和操作的业务逻辑。
view代表ui组件,负责将数据模型转化为ui展现出来。
view-model是一个同步view和model的对象
在这种架构下,view和model之间没有直接的联系,而是通过viewmodel来进行交互,这种交互是双向的,因此view的数据变化会同步到model中,model中的数据变化也会反映到view中

2.vue与seo
vue的前后端分离不利于seo
解决办法
1.页面预渲染
2.服务端渲染
vue-ssr 官方给的服务端渲染方法

预渲染的使用场景更多是我们所说的静态页面的形式,服务端渲染适合大场景

3.路由采用h5 的history 模式
history API
History.back() 前往上一页 === history.go(-1)
History.forward() 下一页 === history.go(1)
history.replaceState(null, null, ‘hello’);
replaceState方法改变了当前页面的URL,在后面添加了一个’/hello’。不过并没有发出任何request请求,当前窗口仍然停留在之前的页面。*不过这里有个问题,当你点击浏览器的后退按钮时,页面并不会回退到我们通过replaceState方法修改之前的那个URL,而是直接回退到了上一个页面(即我们进入到这个页面之前的那个页面)。*这是因为replaceState方法不会修改浏览器的history,它只是简单地替换了地址栏中的URL。

history.pushState(null, null, ‘hello’);
现在再点击浏览器的后退按钮,你会发现它和你预想的效果一样。因为pushState方法将我们传给它的URL添加到浏览器的history中,从而改变了浏览器的history。

参数
history.pushState([data], [title], [url]); 第二个参数基本被浏览器忽略

参考https://www.cnblogs.com/chaoyuehedy/p/5758143.html

3.MVVM和MVC的区别 和jquery等框架的区别
MVVM和MVC区别不大,都是一种设计思想,主要就是MVC中的controller在MVVM中演变成了viewmodel。
MVVM解决了MVC框架中大量的dom操作使页面渲染性能降低,加载速度慢的问题,提高了用户体验

与jquery的区别
vue数据驱动,通过数据来显示视图层 而不是节点操作
解决了jquery中大量的dom操作使页面渲染性能降低,加载速度慢的问题,提高了用户体验

4.vue的优点
1.轻量级框架,只关心view视图层,大小只有几十kb
2.低耦合
例如view层可以独立于model层变化和修改
3.复用性强
一个viewmodel可以绑定到不同的view上

5.组件之间的传值
。父组件向子组件传值
父组件在标签上绑定一个属性 给属性绑定数据
子组件通过props接收数据

。子组件向父组件传值
子组件通过$.emit传递

非父子组件间的数据传递,兄弟组件传值:vuex 或者eventbus
6.路由跳转
声明式跳转

<router-link to=“”>

编程式跳转
this.$router.push()

7.如何使用一个自定义组件
首先,在components文件夹下新建xxx.vue
然后需要引入的页面 import
然后在components里注册一下
最后就可以在template里使用这个标签了

注意的是 如果是用连字符命名的组件 引入的时候使用驼峰的形式!!!!

8.实现按需加载
不进行按需加载
import xx from ‘xxxx’
按需加载

require.ensure([], () => {require('xxxx')})

9.vuex
vuex是什么?
vue中的状态管理
怎么使用?
在main.js中引入store并且注册
然后新建一个store目录存放相应的js
什么场景使用?
组件中需要共享的状态就可以使用 例如 购物车 或者音乐播放器的播放列表等等
使用vuex的好处?
可维护性增强 可读性强 减少耦合

vuex有几种属性
state mutation getter actions module
只用来读取的状态集中放在state中;
改变状态的方式是提交mutations,这是个同步的;
异步逻辑应该封装在action中。
getters类似vue的计算属性,主要用来过滤一些数据。
modules
项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
 }
const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
 }

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
})

ajax请求写在methods里还是vuex 的actions里?
如果请求来的数据只在当前组件使用 那么就写在methods里 如果多个组件需要使用 那么写进vuex

10.v-show和v-if
v-show是 通过修改元素的display的css属性达到显示和隐藏
而v-if直接销毁和重建dom达到
v-if是惰性的 如果一开始条件为假 v-if什么也不做 只有在第一次条件为真的时候 才会开始 渲染条件块内容
v-show不管条件真假 一定会渲染

11.如何让css只在当前组件生效
在 当前 组件的style标签添加scoped

12.keep-alive的作用
keep-alive包裹动态组件时,会缓存组件实例,主要用于保留组件状态避免重新渲染

13.v-el的作用
提供一个在页面上已经存在的dom元素作为Vue实例挂载目标

14.生命周期

created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。

15.watch和computed
computed 是计算一个新的属性,并将该属性挂载到 vm(Vue 实例)上,而 watch 是监听已经存在且已挂载到 vm 上的数据,所以用 watch 同样可以监听 computed 计算属性的变化

computed是惰性观察, 具有缓存性,当数据发生变化后,访问computed才会重新计算,而watch只要数据发生了变化,就 会调用回调

从使用场景上说
computed是计算属性 依赖其他属性计算所得出的值 可以 看做是一个 多对一的关系
watch是监听一个值的变化,这个值的变化会影响其他属性的变化 可以看做是一个 一对多的关系

16.active-class对应的是哪个组件的属性
vue-router模块的router-link组件

17怎么定义vue-router的动态路由
在router目录下的index.js 在path属性后面加“/:id”

18.router有哪几种导航钩子
三种
第一种 全局导航钩子 一般用来判断权限,以及以及页面丢失时候需要执行的操作
包括beforeEach、afterEach

router.beforeEach((to, from, next) => {
    //会在任意路由跳转前执行,next一定要记着执行,不然路由不能跳转了
  console.log('beforeEach')
  console.log(to,from)
  //
  next()
})
//
router.afterEach((to, from) => {
    //会在任意路由跳转后执行
  console.log('afterEach')
})

第二种单个路由钩子 主要用于写某个指定路由跳转时需要执行的逻辑
只有beforeEnter

 routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]

第三种 路由组件
beforeRouteEnter、beforeRouteLeave、beforeRouteUpdate

  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }

19.生命周期
什么是生命周期?
vue实例从创建到销毁的过程
包括 开始创建、初始化数据、编译模板、挂载dom、渲染和更新、卸载 一系列过程

生命周期的 作用?
生命周期中有很多钩子,方便我们控制整个vue实例过程中的逻辑

生命周期总共有几个阶段?
8个阶段
创建前/后
载入前/后
更新前/后
销毁前/后

dom渲染在哪个阶段完成?
mounted阶段已经完成

简述每个生命周期适用场景?
beforeCreate:可以添加一个loading事件 在加载实例时触发
created 初始化完成需要触发的事件写在这里 例如结束上面loading事件。异步请求也适合在这里
beforeMount
mounted 挂载元素 获取到dom节点
beforeUpdate 数据更新前触发
updated 可以添加对数据做一个统一处理的事件
beforeDestroy 可以写一个确认销毁页面的弹窗
destroyed 例如slider组件页面销毁后清空timer

20.vue的一些指令
v-if和v-show
v:bind:class 绑定属性
v-model 双向绑定
v-for 循环

21.vue-loader是什么 ?作用?
是一个vue文件的加载器
作用 让js可以使用es6 style可以使用sass less stylus等等 让template可以使用jade等

22.scss是什么 ?在vue-cli中使用步骤 ?特性?
scss是css的预编译语言

使用步骤
1.安装css-loader sass-loader等加载模块
2.在build目录下找到webpack.base.config 在extends属性中加一个scss的拓展
3.在同一个 文件下 配置module
4.最后在组件的style标签上添加lang=”scss"

特性
可以使用变量 例如将项目的一些字体背景色等等保存成变量 方便维护
可以使用嵌套的写法
可以使用mixin

23.为什么要用 v:bind key
当有相同标签名的元素切换时,需要通过key来让vue区分他们,否则vue为了效率只会替换相同标签的内部元素

24.vNode是什么? 虚拟dom是什么?
vue在页面上渲染的节点,及其子节点成为虚拟节点 也就是vNode
虚拟Dom是 vue组件树建立起来的整个vNode的组件树的称呼

25.vue的双向绑定
主要是采用了数据劫持和发布订阅模式
通过Object.defineProperty来劫持各个属性的getter、setter
在数据变化的时候发布消息给订阅者,触发相应的监听回调

<body>
    <div id="app">
    <input type="text" id="txt">
    <p id="show"></p>
</div>
</body>
<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

26.vue-cli如何新增自定义指令?
1.创建局部指令

var app = new Vue({
    el: '#app',
    data: {    
    },
    // 创建指令(可以多个)
    directives: {
        // 指令名称
        dir1: {
            inserted(el) {
                // 指令中第一个参数是当前使用指令的DOM
                console.log(el);
                console.log(arguments);
                // 对DOM进行操作
                el.style.width = '200px';
                el.style.height = '200px';
                el.style.background = '#000';
            }
        }
    }
})

2.全局指令

Vue.directive('dir2', {
    inserted(el) {
        console.log(el);
    }
})
3.指令的使用

<div id="app">
    <div v-dir1></div>
    <div v-dir2></div>
</div>

27.vue如何自定义一个过滤器?

html代码:

<div id="app">
     <input type="text" v-model="msg" />
     {{msg| capitalize }}
</div>
JS代码:

var vm=new Vue({
    el:"#app",
    data:{
        msg:''
    },
    filters: {
      capitalize: function (value) {
        if (!value) return ''
        value = value.toString()
        return value.charAt(0).toUpperCase() + value.slice(1)
      }
    }
})
全局定义过滤器

Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})

28.$route和 $router的区别
答:route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

29.vue.js的两个核心是什么
数据驱动、组件系统

30.vue常用的修饰符?
.prevent: 提交事件不再重载页面;.stop: 阻止单击事件冒泡;.self: 当事件发生在该元素本身而不是子元素的时候会触发;.capture: 事件侦听,事件发生的时候会调用

31.vue等单页面应用及其优缺点
优点数据驱动、组件化、轻量、简洁、高效
缺点 不利于seo 第一次加载耗时比较长 浏览器的前进后退无法使用

32.Vue 组件 data 为什么必须是函数
1.每个组件都是 Vue 的实例。
2.每个实例需要维护被返回对象的一份独立的拷贝
总而言之就是避免某个实例 改变了 其他的实例都会被影响

33.怎么快速定位哪个组件出现性能问题
通过 chrome有个 performance 来查看每个函数的调用时常,定位出哪个函数的问题,从而能判断哪个组件出了问题。

34.深入理解computed
原理就是 依赖收集、动态计算
与此相关的两个类
dep 一个订阅者列表类 可以增加或者删除订阅者 也可以向订阅者发送消息
watcher 订阅者类 初始化的时候接收getter和callback作为参数 ,getter用来计算watcher对象的值,
当watcher被触发的时候,重新调用getter来计算值,如果值改变 ,就执行callback

https://blog.csdn.net/sinat_17775997/article/details/82682972
参考 https://segmentfault.com/a/1190000010408657

就是当页面重新渲染(不是刷新)的时候,计算属性不会变化,直接读取缓存使用,适合较大量的计算和改变频率较低的属性,

而method,就是当页面重新渲染的时候(页面元素的data变化,页面就会重新渲染),都会重新调用method

37.什么是vDom?
虚拟dom 用js模拟dom 把dom变化的对比 放在js层来做,提高重绘性能

核心api
h函数 其实是个createElement函数

在这里插入图片描述

patch函数
有两种情况
patch(container, vNode) 第一次渲染 把所有节点渲染到空的container中
patch(vNode, newNode) 当之前的渲染的node有改变 新旧node对比 只找出 需要更新的地方来更新,其他地方不变

代码请参考snabbdom(vue用它来实现的vDom)

在这里插入图片描述

diff算法
什么是diff算法
是linux的基础命令
在命令行使用diff a.text b.text 会返回两个文件的区别 (linux

window 下面 可以使用 git diff

vdom为什么要使用diff算法
dom操作耗费性能,必须减少dom操作
找出本次dom需要更新的节点更新,其他不更新
这个找出的过程就需要diff算法

在这里插入图片描述

diff算法的实现
diff 的实现主要通过两个方法,patchVnode 与 updateChildren 。
patchVnode 有两个参数,分别是老节点 oldVnode, 新节点 vnode 。主要分五种情况:

if (oldVnode === vnode),他们的引用一致,可以认为没有变化。
if(oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text),文本节点的比较,需要修改,则会调用Node.textContent = vnode.text。
if( oldCh && ch && oldCh !== ch ), 两个节点都有子节点,而且它们不一样,这样我们会调用 updateChildren 函数比较子节点,这是diff的核心,后边会讲到。
if (ch),只有新的节点有子节点,调用createEle(vnode),vnode.el已经引用了老的dom节点,createEle函数会在老dom节点上添加子节点。
if (oldCh),新节点没有子节点,老节点有子节点,直接删除老节点。

updatechildren
图解updateChildren

终于来到了这一部分,上面的总结相信很多人也看得一脸懵逼,下面我们好好说道说道。(这都是我自己画的,求推荐好用的画图工具…)

粉红色的部分为oldCh和vCh
在这里插入图片描述

我们将它们取出来并分别用s和e指针指向它们的头child和尾child

在这里插入图片描述

现在分别对 oldS、oldE、S、E 两两做 sameVnode 比较,有四种比较方式,当其中两个能匹配上那么真实dom中的相应节点会移到Vnode相应的位置,这句话有点绕,打个比方

如果是oldS和E匹配上了,那么真实dom中的第一个节点会移到最后
如果是oldE和S匹配上了,那么真实dom中的最后一个节点会移到最前,匹配上的两个指针向中间移动
olds和s匹配 olde和e匹配就位置不变
如果四种匹配没有一对是成功的,那么遍历 oldChild , S 挨个和他们匹配,匹配成功就在真实dom中将成功的节点移到最前面,如果依旧没有成功的,那么将 S对应的节点 插入到dom中对应的 oldS 位置, oldS 和 S 指针向中间移动。

http://www.bslxx.com/a/vue/mianshiti/2018/0306/1812.html
https://blog.csdn.net/sinat_17775997/article/details/83751972

vue的三要素
响应式、模板引擎、渲染

一.响应式
什么是响应式?
修改data之后,vue立刻监听到
data属性被代理到vm上(vue的实例)
核心是 Object.defineProperty

<body>
    <div id="app">
        <p>{{name}}</p>
        <p>{{age}}</p>
    </div>
</body>
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.min.js"></script>
<script>
    // 直接在控制台 vm.age = 100 页面也会修改
    // 为什么不是vm.data.age来修改 这些data属性直接被代理到了vm上了?
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'zhangsan',
            age: 99
        }
    })

    
    
    // es5就有这个方法  可以监听读写
    var obj  = {}
    name = 'zhangsan'
    Object.defineProperty(obj , 'name', {
        get: function () {
            console.log('get')
            return name
        },
        set: function (newVal) {
            console.log('set')
            name = newVal
        }
    })
    console.log(obj.name)
    obj.name = 'haha'
    console.log(obj.name)

    // 以上打印顺序为 get zhangsan set get haha
  // 模拟实现vue的响应式
    var mv = {}
    var data  = {
        price: 100,
        name: 'zhangsan'
    }
    
    var key, value
    for (key in data) {
        (function (key) {
            Object.defineProperty(mv, key, {
                get: function () {
                    return data[key]
                },
                set: function (newVal) {
                    data[key] = newVal
                }
            })
        })(key)
    }

二.模板引擎
什么是模板?
本质是字符串
有逻辑 例如 v-for v-if等等
和html类似 但不相同,最后还是需要html来渲染
会转化为js ,因为,首先 他有逻辑,其次 要转化为html渲染,需要 js处理,

以下就是一个模板

<div id="app">
    <div>
      <input v-model="title">
      <button v-on:click="add">submit</button>
    </div>
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>

render函数
with函数的用法(render中有使用 平时开发不建议使用)

var obj = {
    name: 'lisi',
    age: 11000,
    hello: function () {
        console.log('hello')
    }
}

// 不使用with函数
function fn() {
    console.log(obj.name)
    console.log(obj.age)
    obj.hello()
}

fn()

    // 使用with
    function f1() {
        with (obj) {
            console.log(name)
            console.log(age)
            hello()
        }
    }

    f1()

with方法可以方便的来引用某个对象中的属性,但是不能给对象添加属性

下面是render函数的基本用法
比如如下我想要实现如下html:
在这里插入图片描述

我们来尝试使用 render函数重写上面的demo,如下:
在这里插入图片描述

1.模板中所有信息都包含在了 render 函数中
2.this 即 vm
3.price 即 this.price 即 vm.price, 即 data 中的 price
4._c 即 this._c 即 vm._c

在这里插入图片描述

通过控制台打印,我们就知道了 _c就是一个创建dom 元素的方法, _v 是一个创文本节点的方法, _s 是 toString 方法。
vm._c 和vnode中的h函数类似 也是返回vnode,然后在updateComponent里使用patch,分为首次渲染,和不是第一次渲染两种情况

三.渲染
在这里插入图片描述
模板是如何渲染成HTML的?

第一步: 解析模板成 render 函数
with 用法
模板中的所有信息都被 render ,函数包含
模板中用到的 data 中属性,都变成了 JS 变量
模板中的 v-model v-for v-on 都变成了 JS 逻辑
render 函数返回 vnode

第二步: 响应式开始监听
为何要监听 get, 直接监听 set 不行吗
data 中有很多属性,有些被用到,有些可能不被用到
被用到的会走 get, 不被用到的不会走 get
未走到 get 中的属性, set的时候我们也无需关心
避免不必要的重复渲染

第三步: 首次渲染,显示页面,且绑定依赖

初次渲染,被get监听,执行 updateComponent,
然后触发vdom 的 patch 方法
patch 将 vnode 渲染成 DOM,初次渲染完成

第四步: data 属性变化,触发 render
修改属性,被响应式的 set 监听到
执行 updateComponent
生成 vnode 和 preVnode, 通过 patch 进行对比
渲染到 html 中

https://segmentfault.com/a/1190000015120229#articleHeader8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值