精华内容
下载资源
问答
  • vue常见面试题总结

    2020-03-21 22:41:23
    怎么定义vue-router的动态路由?怎么获取传过来的动态参数? 答:在router目录下的index.js文件中,对path属性加上/:id, 获取传过来的动态参数通过使用router对象的params.id vue-router有哪几种...
    1. active-class是哪个组件的属性?嵌套路由怎么定义?
      答:active-classvue-router模块的router-link组件

    2. 怎么定义vue-router的动态路由?怎么获取传过来的动态参数?
      答:在router目录下的index.js文件中,对path属性加上/:id, 获取传过来的动态参数通过使用router对象的params.id

    3. vue-router有哪几种导航钩子?
      答:vue-router有三种导航钩子,一种是全局导航钩子:router.beforeEach(to,from,next),作用是跳转前进行判断拦截;第二种:组件内的钩子;第三种:单独路由独享组件

    4. scss是什么?安装使用的步骤是?有哪几大特性?
      答:预处理css,把css当前函数编写,定义变量,嵌套。 先装css-loadernode-loadersass-loader等加载器模块,在webpack-base.config.js配置文件中加多一个拓展extenstion,再加多一个模块:module里面testloader

    5. scss是什么?在vue.cli中的安装使用步骤是?有哪几大特性?
      答:scss是css的预编译

    • 在vue.cli中的安装使用步骤是
      第一步:用npm下三个loadersass-loadercss-loadernode-sass
      第二步:在build目录找到webpack.base.config.js,在那个extends属性中加一个拓展.scss
      第三步:还是在同一个文件,配置一个module属性
      第四步:然后在组件的style标签加上lang属性 ,例如:lang=”scss”

    • 有哪几大特性:

      • 可以用变量,例如($变量名称=值);
      • 可以用混合器,例如()
      • 可以嵌套
    1. mint-ui是什么?怎么使用?说出至少三个组件使用方法?
      答:基于vue的前端组件库。npm安装,然后import样式和jsvue.use(mintUi)全局引入。在单个组件局部引入:import {Toast} from ‘mint-ui’
      组件一:Toast(‘登录成功’);组件二:mint-header;组件三:mint-swiper

    2. v-model是什么?怎么使用? vue中标签怎么绑定事件?
      答:可以实现双向绑定,指令(v-class、v-for、v-if、v-show、v-on)vuemodel层的data属性。绑定事件:<input @click=doLog() />

    3. axios+tp5进阶中,调用axios.post(‘api/user’)是进行的什么操作?axios.put(‘api/user/8′)呢?
      答:跨域,添加用户操作,更新操作。

    4. 什么是RESTful API?怎么使用?
      答:是一个api的标准,无状态请求。请求的路由地址是固定的,如果是tp5则先路由配置中把资源路由配置好。标准有:.post .put .delete

    5. vuex是什么?怎么使用?哪种功能场景使用它?
      答:vue框架中状态管理。在main.js引入store,注入。新建了一个目录store….. export 。场景有:单页应用中,组件之间的状态,音乐播放、登录状态、加入购物车

    11.mvvm框架是什么?它和其它框架(jquery)的区别是什么?哪些场景适合?
    答:一个model+view+viewModel框架,数据模型modelviewModel连接两个
    区别vue数据驱动,通过数据来显示视图层而不是节点操作。
    场景:数据操作比较多的场景,更加便捷。

    1. 自定义指令(v-check、v-focus)的方法有哪些?它有哪些钩子函数?还有哪些钩子函数参数?
      答:全局定义指令:在vue对象的directive方法里面有两个参数,一个是指令名称,另外一个是函数。组件内定义指令:directives
      钩子函数:bind(绑定事件触发)、inserted(节点插入的时候触发)、update(组件内相关更新)
      钩子函数参数:elbinding

    2. 说出至少4种vue当中的指令和它的用法?
      答:v-if:判断是否隐藏;v-for:数据循环出来;v-bind:class:绑定一个属性;v-model:实现双向绑定

    3. vue-router是什么?它有哪些组件?
      答:vue用来写路由一个插件,组件有router-link、router-view

    4. 导航钩子有哪些?它们有哪些参数?
      答:导航钩子有:全局钩子和组件内独享的钩子。beforeRouteEnterafterEnterbeforeRouterUpdatebeforeRouteLeave
      参数:有to(去的那个路由)、from(离开的路由)、next(一定要用这个函数才能去到下一个路由,如果不用就拦截)最常用就这几种

    5. Vue的双向数据绑定原理是什么?
      答:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应的监听回调。

      具体步骤
      第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上settergetter。这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
      第二步compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
      第三步Watcher订阅者是ObserverCompile之间通信的桥梁,主要做的事情是在自身实例化时往属性订阅器(dep)里面添加自己,自身必须有一个update()方法,待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退
      第四步MVVM作为数据绑定的入口,整合ObserverCompileWatcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起ObserverCompile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input)-> 数据model变更的双向绑定效果

    6. 请详细说下你对vue生命周期的理解?
      答:总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

    • 创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。
    • 载入前/后:在beforeMount阶段,vue实例的$eldata都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
    • 更新前/后:当data变化时,会触发beforeUpdateupdated方法。
    • 销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
    1. 请说下封装 vue组件的过程?
      答:首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

    2. 你是怎么认识vuex的?
      答:vuex可以理解为一种开发模式或框架。比如PHPthinkphp,java有spring等。
      通过状态(数据源)集中管理驱动组件的变化(好比springIOC容器对bean进行集中管理)。
      应用级的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。

    3. vue-loader是什么?使用它的用途有哪些?
      答:解析.vue文件的一个加载器,跟template/js/style转换成js模块。
      用途:js可以写es6style样式可以scsslesstemplate可以加jade

    4. 请说出vue.cli项目中src目录每个文件夹和文件的用法?
      答:assets文件夹是放静态资源;components是放组件;router是定义路由相关的配置;view视图;app.vue是一个应用主组件;main.js是入口文件

    5. vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?
      答:
      第一步:在components目录新建你的组件文件(smithButton.vue)script一定要export default {}
      第二步:在需要用的页面(组件)中导入:import smithButton from ‘../components/smithButton.vue’
      第三步:注入到vue的子组件的components属性上面,components:{smithButton}
      第四步:在template视图view中使用,<smith-button> </smith-button>
      问题有:smithButton命名,使用的时候则smith-button

    6. 聊聊你对Vue.jstemplate编译的理解?
      答:简而言之,就是先转化成AST树,再得到的render函数返回VNodeVue的虚拟DOM节点)
      详情步骤

    • 首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 即源代码的抽象语法结构的树状表现形式),compilecreateCompiler的返回值,createCompiler是用以创建编译器的。另外compile还负责合并option
    • 然后,AST会经过generate(将AST语法树转化成render funtion字符串的过程)得到render函数,render的返回值是VNodeVNodeVue的虚拟DOM节点,里面有(标签名、子节点、文本等等)。
    展开全文
  • vue基础常见面试题

    2020-12-18 12:00:53
    常见面试题 v-text 和 v-html 的区别和相似 答:v-text 与 v-html 的区别是:v-text 输出的是纯文本,浏览器不会再进行 html 解析,但 v-html 会将其当成 html 标签解析后输出。 v-if 和 v-show 的区别和相似 答...

    常见的面试题

    1. v-text 和 v-html 的区别和相似
      答:v-text 与 v-html 的区别是:v-text 输出的是纯文本,浏览器不会再进行 html 解析,但 v-html 会将其当成 html 标签解析后输出。
    2. v-if 和 v-show 的区别和相似
      答:相同点:v-if 与 v-show 都可以动态控制 dom 元素显示隐藏
      不同点:v-if 显示隐藏是将 dom 元素整个添加或删除,而 v-show 隐藏则是为该元素添加 css–display:none,dom 元素还在。
    3. watch 和 computed 的区别和相似
      两者都是对数据进行监听
    • watch
      只要被绑定数据发生改变 watch就会响应 适合用在异步上
    • computed
      需要主动调用 具有缓存能力,只有数据再次改变才会重新渲染,否则会用缓存中的数据
    1. mixins 混入,混合用过?
      答:用过。不推荐使用,因为会出现重名问题,导致项目崩溃,并且不好跟踪。它会影响全局,所以不在项目中使用。
    2. 列举十个指令
      v-if,v-else-if,v-else,v-on,v-model,v-for,v-show,v-bind,v-text,v-html,v-once
    3. 说一下生命周期
      创建阶段(第一次页面加载时执行) beforeCreate,created
      挂载阶段(第一次页面加载时执行) beforeMount,mounted
      更新阶段 beforeUpdate,updated
      销毁阶段 beforeDestroy,destroyed
    4. 组件通信有哪些?
      父传子:父组件使用 v-bind 给子组件添加一个自定义属性,自定义属性接收一个数据,子组件使用 props 接收该数据。
      子传父:父组件使用自定义方法向子组件传入一个函数,子组件使用$emit 方法调用该函数,并传入数据,完成子传父通信。
      父子互相通信:使用.sync 修饰符,使用 v-model。
      跨级通信:vuex
    5. 购物车 vue 怎么做?
      1).利用 v-model 指令,把数据双向绑定到购物车清单中;
      2).利用 computed 来计算购物清单数据是否全选;
      3).利用自定义函数实现加减单品数量事件,及删除单品;
      4).利用 computed 来计算所有选中商品的单价和数量。
    6. 全选反选用 vue 怎么做?
      vue 实现全选和反选,使用 vue 的 computed 来实现
      全选:如果父级选中了,那么子集中所有 checked=true,再次点击取反;如果子集所有 checked=true 时父级 checked=true;
      反选:判断子集的 checked 的值,直接取反。
    7. 跨域的方式,原理
      跨域方式:ajax,jsonp,axios
      jsonp 原理:动态创建 script 标签,使用 script 的 src 进行跨域
    8. 本地存储的相同点不同点
      答:- 生命周期 -体积大小 -功能性
      相同点:这三者都是存储在浏览器本地的
      不同点:1. localStorage 和 sessionStorage 的大小都是 5mb 左右,cookie 的大小为 4kb 左右;
      2.localStorage 如果不清除永远都在,sessionStorage 关闭浏览器的时候会自动清除,cookie 可以设置过期时间,如果不设置的话,关闭浏览器的时候会自动清除;
      3.cookie 可以通过 http 协议进行传递,前提是同源。
    9. 原型,原型链,对象的关系
      1>构造函数 Fn 身上有属性 prototype 为原型对象,原型对象内有 constructor 属性指向当前 prototype 所在的构造函数 Fn
      2>在 new 执行构造函数 Fn 时,创造了一个实例对象 f,实例对象 f 的__proto__指向构造函数 Fn 的原型 prototype
      3>因为实例对象 f 的__proto__指向构造函数 Fn 的原型 prototype,所以实例对象 f 可以间接访问到 Fn 原型 prototype 的方法
    10. ajax 的步骤
      (1)创建 XMLHttpRequest 对象,也就是创建一个异步调用对象.
      (2)创建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、URL 及验证信息.
      (3)设置响应 HTTP 请求状态变化的函数.
      (4)发送 HTTP 请求.
      (5)获取异步调用返回的数据.
      (6)使用 JavaScript 和 DOM 实现局部刷新.
    11. 项目介绍
      。。。
    12. vue 的好处有哪些?
    • 单页面应用,无刷新跳转路由
    • 模块化开发,便于维护和迭代
    • 强大的生态圈,开发快速
    展开全文
  • vue - 常见面试题汇总

    千次阅读 多人点赞 2021-03-23 20:07:29
    1.vue 的生命周期 1-1 钩子函数 1-1-1.创建 beforecreate 第一个钩子,这个阶段的data,methods,computed以及watch的数据和方法不能被访问 create 是实例创建完成后发生的。这个阶段完成数据观测,可以使用数据,...

    一 基础知识

    1.vue 的生命周期

    1-1 钩子函数

    创建

    beforecreate
    第一个钩子,这个阶段的data,methods,computed以及watch的数据和方法不能被访问

    created
    是实例创建完成后发生的。这个阶段完成数据观测,可以使用数据,更改数据,无法与Dom进行交互,想要的话可以通过nextTick来访问

    挂载

    beforeMount

    发生在页面渲染之前,当前阶段虚拟Dom已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updated。

    mounted

    在挂载完成后发生,在当前阶段,真实的Dom挂载完毕,数据完成双向绑定,可以访问到Dom节点,使用$refs属性对Dom进行操作。

    补:第一次页面加载就会触发 创建和挂载钩子

    更新

    beforeUpdate

    发生在更新之前,也就是响应式数据发生更新,虚拟dom重新渲染之前被触发,你可以在当前阶段进行更改数据,不会造成重渲染。

    updated

    发生在更新完成之后,当前阶段组件Dom已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新。

    补充

    activited

    keep-alive专属,组件被激活时调用

    deactivited
    keep-alive专属,组件被销毁时调用

    销毁

    beforeDestroy

    发生在实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,比如清除计时器

    destroyed

    发生在实例销毁之后,这个时候只剩下了dom空壳。组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁。

    1-2 钩子函数的使用方法

    1.beforecreate: data 和 $el 都没有初始化 全部为 undefined,可以在加个loading事件,在加载实例时触发 ,

    2.created: 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用

    3.mounted: 挂载元素,获取到dom节点

    4.beforeUpdate 可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

    5.updated: 可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,
    因为这可能会导致更新无限循环。 该钩子在服务器端渲染期间不被调用。

    6.beforeDestroy : 可以做一个确认停止事件的确认框

    7.destroyed 可以执行一些优化操作,清空定时器,解除绑定事件

    1-3 父子组件生命周期构造函数执行顺序

    加载渲染过程
    父 beforecreate,created,beforeMount
    子 beforecreate,created,beforeMount
    子 mounted
    父 mounted

    子组件更新过程
    父 beforeUpdate
    子 beforeUpdate
    子 Updated
    父 Updated

    父组件更新过程
    父 beforeUpdate
    父 Updated

    销毁过程
    父 beforeDestroy
    子 beforeDestroy
    子 destroyed
    父 destroyed

    如果常用的数据如果需要传递到子组件的话,最好在created 或者 beforemount,把数据请求回来,然后传递给子组件

    2 v-show 与 v-if v-for

    2-1.v-show 与 v-if 的区别

    共同:

    根据真假切换元素的显示状态

    不同:

    v-show :修改元素的display,实现显示隐藏

    (适合频繁切换,在第一次渲染的时候已经消耗了性能)
    v-show则无论初始条件是否成立,都会渲染标签,它仅仅做的只是简单的CSS切换
    

    v-if : 通过操控DOM值来 实现 显示隐藏

    (不适合频繁切换. 数据多不建议用if.每一次切换则重新消耗性能.乱) 
    v-if是惰性的,只有当条件为真时才会真正渲染标签;如果初始条件不为真,则v-if不会去渲染标签。
    

    2-2 v-if 和v-for的优先级

    当v-if 与 v-for 一起使用时,v-for 比v-if 优先级高,如果连用的话会把 v-if 给每个元素都添加一下,会造成性能问题,所以不推荐v-if和v-for在同一个标签中同时使用。

    原因:先有循环才能渲染

    解决方法:
    1、ul 和 li 搭配使用,或者是渲染父级标签下的子标签。

    <ul v-if = "state">
      <li v-for = "(item,id) in list" :key="id"></li>
    </ul>
    

    2,将v-if写成和v-for同级

    <div v-for='(item,id) in list' :key='id' v-if='item.userRank'>
    

    3、使用过滤器将v-if中的判断转移到computed的计算属性中。

    <ul>
       <li v-for"(item,id) in list" :key = "id"></li>
    </ul>
    computed: {
      formList: function(){
         return this.list.filter(function(item){
            return item.state;
        })
      }
    }
    

    补:过滤器
    filter()方法 对原数组的元素进行过滤,返回到一个新的数组中去。不影响原始的数组。、callback需要返回布尔值

    为true的时候,对应的元素留下来,
    为false的时候,对应的元素过滤掉

    3.组件通信有哪些方式?

    3-1.父传子

    思路:

    1.传递:在父组件调用子组件的位置 绑定属性
    (属性名:需要发送的变量名)

    2.接收:子组件通过 props接收
    (props: [属性名])

    type: Number, 数据类型
    required: true , 必须传值
    default: 100 默认携带的数字
    
      props: {
        provinceNumId: {
          type: String,
          required: true
        },
        list: {
          type: Array,
          default() {
            return [];
          }
        },
        studentModalData: {
          type: Object,
          default() {
            return {}
          }
        }
     }
    

    3-2.子传父

    思路:

    1.传递: 在调用子组件的位置 添加自定义事件 使用$emit 发送数据

    2.接收: 通过created 接收数据

    3-3.兄弟传值

    思路:

    1.定义中央事件总线 let bus = new Vue();

    2.传递: 触发自定义事件 并发送 bus.emit (要出发的事件名,要发送的数据)

    3.接收: 触发mounted 并接收 bus.on(要出发的事件名,要接收的数据)

    4.销毁: 在beforeDestroy中 bus.$off 进行销毁,否则会出现重复触发事件的问题

    3-4.公共传递

    思路:

    1.**传递:**在父组件内部添加 provide:{命名:‘内容’} 并赋明需要具体传递的值,

    2.**接收:**在子或者子子 内部 inject:[“命名”] 接收

    3.在相对应页面中可直接获取

    补:组件传值代码参考:
    https://blog.csdn.net/weixin_55042716/article/details/114434354

    4 computed和watch ,有什么区别

    4-1.computed 计算属性

    1. 支持缓存,只在依赖的数据发生变化时,才会重新计算,否则当多次调用computed属性时,调用的其实是缓存;
    2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
    3. 如果一个数据需要经过复杂计算就用 computed
    4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,(某个属性受多个属性影响)
    var var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })
    

    4-2.watch 侦听器

    1. 不支持缓存,每调用一次就计算一次;
    2. watch支持异步;
    3. 如果一个数据需要被监听并且对数据做一些操作就用 watch
    4. 当一个属性发生变化时,需要执行对应的操作;一对多(监听多个数据)
    <div id="app">
        <input type="text" v-model="num">
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                num: ''
            },
            watch: {
            	firstName: {
        			handler(newName, oldName) {
          				this.fullName = newName + ' ' + this.lastName;
        			},
       				 // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
        			immediate: true,
        			// 开启深度监听:只要firstName中的任何一个属性发生改变,都会触发相应的代码
              		deep: true
      			},
                num(newVal, oldVal) {
                // 监听 num 属性的数据变化
        		// 作用 : 只要 num 的值发生变化,这个方法就会被调用
        		// 第一个参数 : 新值
        		// 第二个参数 : 旧值,之前的值
                    console.log('oldVal:',oldVal)
                    console.log('newVal:',newVal)
                }
            }
        })
    
    </script>
    

    4-3.methods 方法

    1. 不支持缓存, 只要使用该方法便进行调用。

    5 Vue中的 data 为什么必须是函数

    vue组件中data值不能为对象,因为对象是引用类型,每个组件的data都是内存的同一个地址,如果修改一个对象里面的数据,其他的也会被影响到,
    data 如果是一个函数,每一个函数都有自己的局部作用域,他改变的话不会影响到其他的数据。

    6 Vue中的 key 有什么作用?

    列表渲染时的唯一性

    6-1.添加减少值

    例:
    [1,2,3,4,5,]
    添加一个a
    [1,2,a,3,4,5,]

    不加key 则 3,4,5 会重新渲染一遍 a成3 ,3成4, 4成5

    加key 则只单独渲染新插入的值

    减少
    [1,2,4,5,]
    加key,如果有一项移出,后面的不会错位,用于删除操作

    6-2 条件渲染中的key

    不加key:
    vue无法判断每个组件的不同,则会重复使用相同的组件,会拿到上一个组件的信息,

    加key:
    对于vue来说,每个组件都是不同的,切换时,都会重新渲染,
    (如果不重新渲染的话,不会触发生命周期函数,没法请求新的数据)

    6-3 总结:

    无:key属性时,状态默认绑定的是位置; 删除所有,重新渲染,
    有:key属性时,状态根据key的属性值绑定到了相应的数组元素。删除某一条不会重新渲染,节省性能,

    6-4 建议:

    不使用index作为key的值,使用唯一id作为标识.(后台提供或自己创建)

    7 vue 路由

    7-1 路由的理解

    通过互联的网络把信息从 (源地址) 传输到 (目的地址) 的活动
    映射表:地址和具体某一台电脑之间的关系

    7-2 vue-router 路由模式有几种?

    1.hash路由 – 默认模式

    在地址栏会有一个#号,
    因为hash发生变化的url都会被浏览器记录下来,浏览器的前进后退都可以用了,同时点击后退时,页面字体颜色也会发生变化。
    这样一来,尽管浏览器没有请求服务器,但是页面状态和url一一关联起来,
    后来人们给它起了一个霸气的名字叫前端路由,成为了单页应用标配。

    2.history路由

    有的back、forward、go 方法

    history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法。提供了对历史记录进行修改的功能。它能让开发人员在不刷新网页的情况下改变站点的 URL
    History 有 URL 重定向问题,需要在服务端去配置 url 重定向,否则会报 404 错误。

    404
    history模式下,前端的url必须和实际向后端发起请求的url 一致,如http://www.abc.com/book/id 。如果后端缺少对/book/id 的路由处理,将返回404错误。

    3.Abstract

    abstract 模式针对的是没有浏览器环境的情况,比如 Weex 客户端开发,内部是没有浏览器 API 的,
    那么 Vue-Router 自身会对环境做校验,强制切换到 abstract 模式,
    如果默认在 Vue-Router 的配置项中不写 mode 的值,
    在浏览器环境下会默认启用 Hash 模式,在移动客户端下使用 abstract 模式。

    3.将hash模式修改为history模式

    const router = new VueRouter({
    	routes,
    	mode:'history'
    })
    

    7-3 router和route的区别

    1 $router
    用来操作路由 只写对象
    提供了一些方法 go back

    2 $route
    用来获取路由的信息 只读对象
    存放路径 path params参数 query

    //操作 路由跳转
    this.$router.push({
          name:'hello',
          params:{
              name:'word',
              age:'11'
         }
    })
    //读取 路由参数接收
    this.name = this.$route.params.name;
    this.age = this.$route.params.age;
    

    7-4 params传参 跟query传参

    7-4-1 params :

    this.$route.params.xxx

    params 只能用name来引入路由

    params 是路由的一部分,必须要在路由后面添加参数名。

    params 相当于post请求,参数不会再地址栏中显示。

    刷新页面之后参数会消失
    路由里就要这样写

       this.$router.push({name:'Detail',params:{pro_id:pro_id}});
    

    router - index.js 路由设置,参数名保持一致。

    	{
          path: '/Detail/:pro_id', //配置参数,防止刷新数据丢失
          name: 'Detail',
          component: Detail
        },
    

    7-4-2 query :

    this.$route.query.xxx

    query 传参使用path,name来引入路由。

    query是拼接在url后面的参数,没有在路由后面添加参数名也没关系。

    query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,

    7-4-3 props

    在路由对象内,通过props属性 开启传参功能
    在组件对象内 通过props接收
    原因: 为了降低路由和组件的耦合度,

    路由页面,设置 props:true
    页面 props:[‘id’]

    在子detial中设置
     {
      path:'/detial:id',
      name:'detail',
      components:{
        default:()=> import(/* webpackChunkName: "pro" */'@/views/detail/detail.vue')
      },
      props:{
        default:true
      }
     }
    

    7-5 路由跳转

    7-5-1导航模式

    <router-link to="path">xxx</router-link>
    
        to 要跳转到的路由规则 string|object 
        to="users" 
        :to="{path:'path'}"  
        tag  可以指定渲染成什么组件
        replace 不会留下history记录,浏览器返回前进按钮不能用
        
    

    7-5-2 导航模式

    可以跟点击事件一起用

    this.$router.push("/login"); 
    this.$router.push({ path:"/login" }); 
    this.$router.push({ path:"/login",query:{username:"jack"} });
    this.$router.push({ name:'user' , params: {id:123} }); 
    this.$router.go( n );//n为数字 负数为回退
    
    

    7-5-3 路由重定向

    概念:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面

    实现: 通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向

    7-5-4 嵌套路由

    在路由下 添加子路由

    在父路由组件的模板内容中添加子路由链接和子路由填充位(占坑),同时在路由规则处为父路由配置children属性指定子路由规则:

    routes: [ 
     { 
        path: "/user", 
        component: User, //这个不能丢 
        // 通过children属性为/user添加子路由规则 
        children:[
            { path: "index", component: Index }, 
            { path: "add", component: Add }, 
        ] 
      } 
    ]
    
    需要在 User组件中定义一个router-view 用于嵌套路由的渲染显示
    <router-view></router-view>
    

    7-6 路由守卫

    导航守卫 就是路由跳转过程中的一些 钩子函数 ,这个过程中触发的这些函数能让你操作一些其它事情时,可以进行过滤操作,这就是导航守卫。

    to: 目标路由
    from: 当前路由
    next() 跳转 一定要调用
    next(false);//不让走
    next(true);//继续前行
    next(’/login’)//走哪
    next({path:’/login’,params:{},query:{}})//带点货
    

    全局前置守卫 beforEach

       router.beforeEach((to, from, next) => {
            document.title = to.meta.title || '卖座电影';
            if (to.meta.needLogin && !$store.state.isLogin) {
                next({
                    path: '/login'
                })
            } else {
                next()
            }
        })
    

    路由独享的守卫 beforeEnter
    使用方法与全局守卫相同 不同的是:全局守卫可以作用于全局,路由独享守卫只作用于被设置守卫的路由

    //登录模块
        path: '/login',
        component: () => import('@/views/login'),
        beforeEnter: (to, from, next) => {
           if (to.meta.needLogin && !$store.state.isLogin) {
               next({
                   path: '/login'
               })
            } else {
               next()
            }
         }
    

    组件路由守卫

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

    注意: 路由独享守卫,守的是path 组件内部守卫,守的是component

    8 路由懒加载

    8-1.为什么需要懒加载?

    像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,

    而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时

    8-2.如何实现懒加载

    方法一 resolve

    这一种方法较常见。它主要是使用了resolve的异步机制,用require代替了import,实现按需加载,下面是代码示例

    import Vue from 'vue'
    import Router from 'vue-router'
    Vue.use(Router)
    
    export default new Router({
      routes: [
    //     {
    //       path: '/',
    //       name: 'HelloWorld',
    //       component: HelloWorld
    //     }
    //   更改
            {
              path: '/',
              name: 'HelloWorld',
              component: resolve => require(['@/components/HelloWorld'], resolve)
            }
      ]
    }) 
    

    方法二.import按需加载(官方写法)

    能够被webpack自动代码分割允许将不同的组件打包到一个异步块中,使用命名chunk(特殊注释语法)。

    Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

    const comA = () => import('url')
    const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
    const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
    const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
    

    方法三 webpack提供的require.ensure()

    vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。
    这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。

    {  
        path: '/home',   name: 'home',   
        component: r =>require.ensure([], () => r(require('@/components/home')), 'demo')
     }
    

    9 vue的内置组件 keep-alive -优化

    缓存组件的状态 ,可能会被重复显然的动态组件处,缓存动态组件的状态。避免重复渲染。节约性能
    使用:将要被缓存的组件或可能会被重复渲染的组件,使用 keep-alive包裹即可

    渲染场景 例:

    首页下拉刷新,加载过的数据,切换其他页面后,再返回首页,没有记录,则数据重新请求,添加 keep-alive包裹后,记录数据,不会再重复加载。 切换另一个页面,上一个页面依旧保持活跃,数据继续保持

    应用 :

    根据条件缓存页面

    利用路由的元数据meta 添加

    APP.js页面
    
     <keep-alive>
        <!-- 添加meta的则添加 keep-alive -->
        <router-view v-if="$route.meta.keep"></router-view>
     </keep-alive>
        <!-- 不添加 -->
        <router-view v-if="!$route.meta.keep"></router-view>
    
    路由页面给需要的添加meta
    {
        path: '/',
        name: 'home',
        alias: '/home',
        components:{ home },
        meta:{
          keep:true //需要缓存
        }
      },
      
    

    补充:

    生命周期函数
      1. activated
         在 keep-alive 组件激活时调用
         该钩子函数在服务器端渲染期间不被调用
    
      2. deactivated
    在 keep-alive 组件停用时调用   
    该钩子在服务器端渲染期间不被调用   
    被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子:activated与deactivated   
    使用 keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,
    需要在 activated 阶段获取数据,承担原来 created 钩子函数中获取数据的任务。  
     
    注意: 只有组件被 keep-alive 包裹时,这两个生命周期函数才会被调用,
    如果作为正常组件使用,是不会被调用的,以及在 2.1.0 版本之后,使用 exclude 排除之后,
    就算被包裹在 keep-alive 中,这两个钩子函数依然不会被调用!
    另外,在服务端渲染时,此钩子函数也不会被调用。
    

    10 vue 的混入 mixin -优化

    公共配置
    多个组件中都需要的数据或功能,混入对象内部的选项等同于组件对象的选项,但是混入对象并不是真正的组件对象,必须添加到组件对象内部后才能执行,

    重复方法或重复数据
    — 对象类合并
    — 函数类 将多个函数放在数组中,都执行
    — 重复的数据 以组件内部的为准,

    语法:
    —定义mixin 对象
    — 引入 mixin
    — 使用

     <div id="app">
         <button @click='hello'>测试</button>
     </div>
        
    <script>
    var mymixin ={
       methods:{
          hello:function(){
            console.log('进入了mymixin了')
          }
       }
    }
    
    //进入 vue编程中
     const app = new Vue({
        el:'app',
        mixins:[mymixin],
        data:{}
     })
    </script>
    

    11-1. solt 插槽

    组件的最大特性就是 重用 ,而用好插槽能大大提高组件的可重用能力
    插槽的作用:父组件向子组件传递内容。

    image.png

    通俗的来讲,插槽无非就是在 子组件 中挖个坑,坑里面放什么东西由 父组件 决定

    11-2 匿名插槽

    匿名插槽一般就是使用单个插槽

    //子组件内部
    <div class='banner'>
        <img v-for='item in imgs' :src='item.src' :key='item.bannerId'>
        //占了个位,
        <solt>
        //插槽内部设置了默认值。如果将来插槽没有被插入组件或者元素,就用自己内部的元素来渲染
           <button>组件内部</button>
        </solt>
    </div>
    
    //父组件 
    <banner>
    //如果这里没有设置值,则显示插槽中的内容,
    //设置例了值则显示此处的值
       <button> &lt; </button>
    <banner>
    

    11–3 具名插槽

    slot 元素可以用一个特殊的特性 name 来进一步配置如何分发内容。多个插槽可以有不同的名
    字,具名插槽将匹配内容片段中有对应 slot 特性的元素。

    具名插槽存在的意义就是为了解决在单个页面中同时使用多个插槽。
    如果没有起名的话,默认为default

    //子组件
    <div class='banner'>
        <img v-for='item in imgs' :src='item.src'>
        <solt name="but">
           <button>组件内部</button>
        </solt>
    </div> 
    
    //父组件
    <banner>
       <template v-solt:but>
      //简写 <template #but>
           <button> &lt; </button>
       </template>
    <banner>
    

    11–4 作用域插槽

    应用场景:父组件对子组件的内容进行加工处理
    作用域插槽是一种特殊类型的插槽,作用域插槽会绑定了一套数据,父组件可以拿这些数据来用,
    于是,情况就变成了这样:样式父组件说了算,但父组件中内容可以显示子组件插槽绑定的数据。

    //子组件
     <div>
        <slot text="我是子组件中的内容"></slot>
     </div>
    
    //父组件
    <banner> 
        <div slot-scope="props">
            <div>父组件</div>
            <h3>{{ props.text }}</h3>
        </div>
    </banner>
    

    作用域插槽 相对于匿名插槽 加上 匿名插槽里面携带的信息

    12. nextTick

    12-1 理解

    就是当页面出来的时候,可能静态资源还没配置完成,这个时候要用nexttick延迟回调,更新数据后立即操作dom

    12-2 应用场景

    在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,

    1)在created生命周期中进行dom操作,例如created中通过**$refs**获取子组件的属性或方法。(相当于mounted里操作)

    2)在某个数据改变引起的dom更新后 再进行的操作

    总结:在下一次dom更新循环结束之后执行延迟回调,在修改数据之后使用这个方法,立即更新dom.

    13.对vuex的理解

    集中式的存储管理 应用程序中所有组件的状态
    需要多个组件共享的变量全部存储在一个对象里面
    然后,将这个对象放在顶层的vue实例中,让其他组件可以使用

    13-1 为什么使用它?

    1. vue单向数据流 父级 prop 的更新会向下流动到子组件中,如果组件嵌套过深 通过props层层往下传比较繁琐,在传的过程中容易出现对数据的更改,导致数据紊乱

    2. 如果在一个项目很庞大各个,组件会共用一个状态,所以用到vuex,即可在整个Vue项目的组件中使用。

    13-2.五大核心属性

    概念:

    state 是状态管理器的状态中心,里面是初始化的数据

    mutation 是唯一改变数据的方式 通过commit 提交方法,方法必须是同步的,只能通过mutation 变更Store 数据,不可以直接操作Store 中的数据

    action 就是处理异步操作,让motation中的方法能在异步操作中起作用 通过store.dispatch 来分发actions 中的异步方法,再通过commit提交mutations,进行修改数据

    getter 是状态管理器中的计算属性 主要用来过滤一些数据,可以在多组件之间复用

    module 将 store 分割成模块,每个模块都具有state,mutation、action、getter、甚至是嵌套子模块

    state 是状态管理器的状态中心,里面是初始化的数据

    export default new Vuex.store({
        state:{
            count:0
        }   
    })
    //使用页面:
    <h1>{{ this.$store.state.count }}</h1>
    

    mutation 是唯一改变数据的方式 不在这里面写 异步代码

    export default new Vuex.store({
      state:{
          count:0
        },
      mutations:{
        add(state,step){
           state.count =state.count+step
        }
      }
    })
    
    //使用页面
    <button @click='add1'> mutations测试</button>
    methods:{
       add1(){
         this.$store.commit('add',1)
       }
    }
    // 每次点击 增加 1
    

    actions 就是处理异步操作,让motation中的方法能在异步操作中起作用

    export default new Vuex.store({
      state:{
         count:0
      },
      mutations:{
        add(state,step){
          state.count=state.count+step
        }
      },
     actions:{
       act(context,step){
         setTimeout(() =>{
           context.commit('add',step)
         },3000)
       }
     }
    })
    
    //使用
    <button @click='add2'> actions测试</button>
    
    methods:{
       add2(){
         this.$store.dispatch('act',1)
       }
    }
    // 每次点击 增加1  三秒后执行
    

    getter 是状态管理器中的计算属性

    export default new Vuex.store({
      state:{
         count:0
      },
      getters:{
        powerCounter(state){
           return state.count * state.count
       }
     }
    })
    
    使用:
    <h>{{ $store.getters.powerCounter}}</h>
    

    module 具体去分割模块

    export default new Vuex.store({
      modules :{
        a:{
          state:{
              name:'zs'
          },
          mutations:{},
          actions:{},
          getters:{}
        },
        b:{
          state:{},
          mutations:{},
          actions:{},
          getters:{}
       }
     }
    })
    
    <h1>{{$store.state.a.name}}</h1>
    

    13-3.哪些会用到?

    登录状态,用户名称,头像,购物车的数量,收藏信息,地理位置。所有需要用户信息的地方验证登陆状态。

    13-4 vuex登录注册使用场景

    点击登录按钮的时候,发送axios请求,从后端调用的借口获取数据,返回成功的状态码时,调用vuex里面的mutation方法,动态改变用户和密码的内容,把用户名渲染在用户页面上

    13-5 解决vuex页面刷新数据丢失问题

    原因:vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被清空。

    解决:
    办法一:将vuex中的数据直接保存到浏览器缓存中(sessionStorage、localStorage、cookie)
    办法二:在页面刷新的时候再次请求远程数据,使之动态更新vuex数据
    办法三:在父页面向后台请求远程数据,并且在页面刷新前将vuex的数据先保存至sessionStorage(以防请求数据量过大页面加载时拿不到返回的数据)

      //===========================下面是解决刷新页面丢失vuex数据
      created() {
        //在页面加载时读取sessionStorage里的状态信息
        if (sessionStorage.getItem('store')) {
          this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store'))));
        }
    
        //在页面刷新时将vuex里的信息保存到sessionStorage里
        window.addEventListener('beforeunload', () => {
          sessionStorage.setItem('store', JSON.stringify(this.$store.state));
        });
      }
    

    14 vue中import和require的用法

    1,require是CommonJS规范的模块化语法,import是ECMAScript 6规范的模块化语法;
    2,require是运行时加载,import是编译时加载;
    3,require可以写在代码的任意位置,import只能写在文件的最顶端且不可在条件语句或函数作用域中使用;
    4,require通过module.exports导出的值就不能再变化,import通过export导出的值可以改变;
    5;require通过module.exports导出的是exports对象,import通过export导出是指定输出的代码;
    6,require运行时才引入模块的属性所以性能相对较低,import编译时引入模块的属性所所以性能稍高。

    15 父组件可以监听到子组件的生命周期吗?

    比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现:

    // Parent.vue
    <Child @mounted="doSomething"/>
    // Child.vue
    mounted() {
      this.$emit("mounted");
    }
    

    以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示:

    //  Parent.vue
    <Child @hook:mounted="doSomething" ></Child>
    doSomething() {
       console.log('父组件监听到 mounted 钩子函数 ...');
    },
    //  Child.vue
    mounted(){
       console.log('子组件触发 mounted 钩子函数 ...');
    },     
    // 以上输出顺序为:
    // 子组件触发 mounted 钩子函数 ...
    // 父组件监听到 mounted 钩子函数 ... 
    
    

    当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。

    16 vue项目如何刷新当前页面

    16-1.场景

    在处理列表时,常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求。

    16-2.遇到的问题

    1.用vue-router重新路由到当前页面 页面是不进行刷新的
    2.采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好

    16-3.推荐好用的方法

    16-3-1 思路:

    1、在router-view中加上条件渲染 v-if 默认为true。让它显示出来

    2、写一个reload方法,在页面刷新只有,点击某个查询条件的时候调用这个重载的方法
    这时条件渲染变化了为false
    在修改数据之后使用 $nextTick,
    条件渲染变化了为true
    则可以在回调中获取更新后的 DOM

    3.在需要刷新的页面 注入这个函数
    在需要用到这个函数的地方去引用

    16-3-2 代码展示:

    App.vue 页面

    <template>
      <div id="app">
        <div class="wrap">
        //条件渲染 v-if 默认为true
          <router-view v-if="isRouterAlive"></router-view>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      provide () {
        return {
          reload: this.reload
        }
      },
      data () {
        return {
          isRouterAlive: true
        }
      },
      methods: {
      //reload方法,在页面刷新只有,点击某个查询条件的时候调用这个重载的方法  
        reload () {
          this.isRouterAlive = false
          //修改数据之后
          this.$nextTick(function() {
             this.isRouterAlive = true
          })
        }
      }
    }
    </script>
    

    需要被刷新的页面

    <template>
        <button @click="refresh"></button>
    </template>
    <script>
        export default{
            name: 'refresh',
            //注入这个函数
            inject: ['reload'],
            methods: {
                  refresh () {
                  //引用
                      this.reload()
                  }
            }
        }
    </script>
    

    17.直接给一个数组项赋值,Vue 能检测到变化吗

    由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。

    17-1 对于对象

    对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用
    Vue.set(object, propertyName, value)
    this.$set(this.someObject,'b',2)
    赋值多个
    Object.assign(this.someObject, { a: 1, b: 2 })

    17-2 对于数组:

    Vue.set(vm.items, indexOfItem, newValue) vm.items.splice(indexOfItem, 1, newValue)
    或者
    vm.$set(vm.items, indexOfItem, newValue)

    17-3 数组方法

    push()
    pop()
    shift()
    unshift()
    splice()
    sort()
    reverse()

    可参考:
    https://blog.csdn.net/qq_38280242/article/details/102807862

    18 为何Vue 采用异步渲染

    因为如果不采用异步更新,那么每次更次更新数据都会对当前组件进行重新渲染,所以为了性能考虑,vue 会在本轮更新后,再去异步更新视图

    19 scoped

    当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,

    也就是说,该样式只能适用于当前组件元素。使组件之间的样式不互相污染。

    补:
    但是,在做项目中,会遇到这么一个问题,即:引用了第三方组件,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成组件之间的样式污染。那么有哪些解决办法呢?

    1.创建两个style标签

    <style lang="scss">
      /*添加要覆盖的样式*/
    </style>
    <style lang="scss" scoped>
      /* local styles */
    </style>
    <!--vue官网中提到:一个 .vue 文件可以包含多个style标签。所以上面的写法是没有问题的。-->
    

    2.穿透scoped >>>或/deep/

    <template>
     <div class="box">
      <dialog></dialog>
     </div>
    </template>
    <!--使用 >>>或者 /deep/ 操作符(Sass 之类的预处理器无法正确解析 >>>,可以使用/deep/)-->
    <style lang="scss" scoped>
    .box {
     /deep/ input {
      width: 166px;
      text-align: center;
     }
    }
    </style>
    或者
    <style lang="scss" scoped>
    .box >>> input {
      width: 166px;
      text-align: center;
     }
    }
    </style>
    

    二.原理部分

    1 MVVM?

    M:(model)数据模型
    V:(view)视图 前端展示页面
    VM:(ViewModel)桥梁 用于双向绑定数据与页面,对于我们的课程来说,就是vue的实例

    MVVM 模式 采用双向绑定 将Model 的改变实时的反应到View 中,另一方面它实现了DOM监听 当DOM 发生一些事件(点击 滚动 touch 等)时, 可以监听到,并在需要的情况下改变对应的Data

    优点

    低耦合
    视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

    可重用性
    你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。

    可测试
    界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

    2.vue响应式原理

    采⽤数据劫持结合发布者-订阅者模式的⽅式,通过Object.defineProperty() 来劫持各个属性的setter, getter 在数据变动时发布消息给订阅者,触发相应监听回调,,在属性被访问和修改时通知变化

    new Vue() 会传入一个el , 和数据data , 如果传入的是data ,会被传入一个Observer对象中 ,通过Object.defineProperty 监听劫持的数据data中的各个属性的 set 和get ,给每个属性创建一个Dep 对象,然后添加观察者; 如果传入的是el, 会被传入Compile 对象中解析el 模板中的指令, 然后会初始化到view层中而且每个属性都会创建一个watcher,然后把watcher加入到Dep 对象中;当改变某个属性中的值后,就被监听到这个属性发生改变,就会调用该属性的Dep对象中notify 函数,然后遍历所有的观察者watcher 调用update,去更新view 层
    Object.defineProperty() 此方法会直接在一个对象上定义一个新的属性,或者修改一个对象的现有属性,并返回此对象
    get set 能时刻观察页面变化,然后通过组件渲染函数去改变页面的显示

    Object.defineProperty(obj, prop, descriptor)   
    **obj**  要定义属性的对象。
    **prop**  观察的属性 。
    **descriptor** 要定义选项get set函数。
    get读    set设置
    

    原生JS代码简单实现

    <body>
    	<div id="msg"></div>
    	<input type="text" name="" id="ipt" oninput="change(this)">
    </body>
    <script>
    //1.定义源数据
    	var data={
    		msg:"hello world"
    	}
    // 4.定义 watcher(干活的,可实现通用性,其他页面也可实现) 
    var obj = {}
     Object.defineProperty(obj, "msg", {
    	get (){
    		// 获取msg的值
    		return data.msg
    	},
    	set (datas){
    		// 设定msg的值,更新页面
    		data.msg = datas
    		// 更新值
    		document.getElementById("msg").innerHTML = datas
    		return true
    	}
     })  
    // 2.将数据显示在页面中,(一展示页面就显示)
    document.getElementById("msg").innnerHTML = obj.msg
    document.getElementById("ipt").value = data.msg
    //3.编写oninput 方法处理函数
     function changeVal(ele){
     // 获取到改变之后的新值
    	const inputVal = ele.value
    	// 更新div中的值
    	//document.getElementById("msg").innerHTML = inputVal
    	obj.msg = inputVal
    }
    </script>
    

    2-2 v-model 双向数据绑定

    v-model是 :value=“msg” @input=“msg=$event.target.value” 的语法糖,

    其中 :value=“msg” 是绑定了数据,
    value就是input输入框里的值;
    @input=“msg=$event.target.value” 就是监听input输入框里值的变化,然后改变值。

    一句话概括就是,绑定数据并且监听数据改变

    <div>
    	<input type='text' :value='msg' @input='aaa($event)'>
    	<p>{{msg}}</p>
    </div>
    <script>
      var app = new Vue({
    	el:'#app',
    	methods:{
    	  aaa(eve){
    		this.msg = eve.target.value
    	  }
    	}
      })
    </script>
    

    5.虚拟DOM 原理

    5-1 虚拟DOM原理

    虚拟dom是对真实dom的抽象,本质是JS对象,这个对象就是更加轻量级的对dom的描述

    在渲染页面之前(真实的dom树挂载之前) vue会自己根据真实的dom构建一个虚拟dom,当里面某个节点发生变动时,与旧节点对比一下,发现不一样的地方直接修改在真实对的dom上,就是在虚拟dom上比较新旧节点的同时直接在真实dom上修补

    真实DOM
    <div class="red">
        <span></span>
        <span></span>
    </div>
    
    虚拟DOM
    const app = {
        tag: "div", // 标签名或组件名
        data: {
            class: "red", // 标签上的属性
            on: {
                click: () => {} // 事件
            }
        },
        children: [ // 子元素节点
          {......}
        ],
    }
    
    如何创建虚拟 DOM
    h('div', {
        class: 'red',
        on: {
            click: () => {}
        },
    }, [h('span', {}, 'span1'), h('span', {}, 'span2')])
    

    5-2 优点:

    在某些情况下,虚拟 DOM 比真实 DOM 快,因为虚拟 DOM 能减少不必要的 DOM 操作

    虚拟 DOM 可以减少 DOM 操作:将多次操作合并一次操作,比如在页面里添加1000个div,DOM可能要操作1000次,但是虚拟DOM只需要操作一次(把数据添加到一个数组里然后操作);

    还可以减少DOM操作的范围:虚拟DOM借助DOM diff可以把多余的操作省掉,比如添加1000个div,通过对比区分出哪些是新增的、哪些是重复的,如果只有10个是新增的就只渲染这10个。

    虚拟DOM可以跨平台渲染

    虚拟DOM不仅可以变成DOM,还可以变成小程序、IOS或者安卓应用,虚拟DOM本质上 只是一个JS对象

    5-3 缺点:

    需要额外的创建函数来创建虚拟DOM,但是可以通过JSX语法来简化成XML写法,但是这也有缺点,就是严重依赖打包工具,要添加额外的构建过程
    当数据规模不大(比如有几千个节点的时候),虚拟DOM的确更快,但是如果规模达到一定程度(十万+)的话,虚拟DOM的稳定性不如原生DOM。不过一般也达不到这个规模,所以多数情况下不必考虑。

    6 单页面应用(SPA)

    单页面应用(SPA),页面发生变化时,主要是通过前端的JS来进行控制的,不需要每次访问后台服务器。
    js会感知到 url 的变化,可以使用js动态把当前页面清楚掉,然后显示新的组件。把页面的切换放到前端来控制,而不需要每次都请求后台。

    多页面(MPA),每次页面变化时,都会访问后台服务器,通过后台服务器进行控制页面的切换。每一次页面跳转,服务器都会返回一个不同的文档,这种便称为多页面的应用,每次都返回新的HTML页面。

    7vue渲染过程

    7-1 渲染过程

    Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。但是模板毕竟是模板,不是真实的dom节点。从模板到真实dom节点还需要经过一些步骤

    1 把模板编译为render函数(或在开发环境已完成,vue-loader)
    2 实例进行挂载, 根据根节点render函数的调用,递归的生成虚拟dom
    3 对比虚拟dom,渲染到真实dom
    4 组件内部data发生变化,组件和子组件引用data作为props重新调用render函数,生成虚拟dom, 返回到步骤3

    7-1-2 这样有什么好处呢?

    一个组件对象,如果内部的data发生变化,触发了render函数,重新生成了VNode虚拟节点。那么就可以直接找到所对应的节点,然后直接替换。那么这个过程只会在本组件内发生,不会影响其他的组件。于是组件与组件是隔离的。

    7-2 更新过程

    1,修改data,触发setter(此前在getter中已被监听)
    2,重新执行render函数,生成newVnode
    3,patch(vnode,newVnode)

    9.预编译器less 和 sass

    CSS预处理器,可嵌套class、减少很多重复的选择器,提高样式代码的可维护性。大大提高了我们的开发效率。

    Less 是在客户端处理的。
    Sass 是在服务器端处理的。

    less变量 @变量名:值
    例:@color:pink
    使用:
    body{
    background-color:@color
    }

    less 编译
    vs code安装easy less
    出现my.css
    link 引入

    less嵌套
    子元素嵌套,直接写到父元素里面
    添加伪元素 &:hover

    伪类,交集选择器都用&

    less运算
    加减乘除

    @border:5px (空格) + (空格) 5

    注:运算符左右两侧 敲空格隔开
    如果运算符前后两个都有单位,以第一个单位为准

    三 项目优化

    (1)代码层面的优化

    v-if 和 v-show 区分使用场景
    computed 和 watch 区分使用场景
    v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
    长列表性能优化
    事件的销毁
    图片资源懒加载
    路由懒加载
    第三方插件的按需引入
    优化无限列表性能
    服务端渲染 SSR or 预渲染

    (2)Webpack 层面的优化

    Webpack 对图片进行压缩-------先引入npm install image-webpack-loader --save-dev,然后在 webpack.config.js 中配置
    减少 ES6 转为 ES5 的冗余代码
    提取公共代码
    模板预编译
    提取组件的 CSS
    优化 SourceMap
    构建结果输出分析
    Vue 项目的编译优化

    (3)基础的 Web 技术的优化

    开启 gzip 压缩
    浏览器缓存
    CDN 的使用
    使用 Chrome Performance 查找性能瓶颈

    vue 3.0

    vue 2.0 只有面向对象
    vue 3.0 是对函数式的一种补充 Composition API

    展开全文
  • vue常见面试题讲解

    2019-12-20 09:47:51
    vue常见面试题讲解 1.谈谈你对MVVM开发模式的理解 MVVM分为Model、View、ViewModel三者 Model:代表数据模型,数据和业务逻辑都是在Model层中定义 View:代表UI视图,负责对数据的展示 ViewModel:负责监听Model...

    vue的常见面试题讲解

    1.谈谈你对MVVM开发模式的理解

    • MVVM分为Model、View、ViewModel三者
      • Model:代表数据模型,数据和业务逻辑都是在Model层中定义
      • View:代表UI视图,负责对数据的展示
      • ViewModel:负责监听Model中数据的改变并控制视图的更新,处理用户交互操作

    Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。

    这种模式实现了Model和View的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作dom。

    2.对于组件通信你了解多少,请描述一下你是怎么完成组件的通信的

    • 父传子用 props传递
    • 子传父用$emit传递
    • 非父子之间的传值 建立一个空实例进行传值,中央事件总线机制
    • 祖孙之间的传值可以利用provide inject模式

    VUEX可以处理上述的每一个情况

    3.关于单页应用首屏加载速度慢,出现白屏时间过长问题你怎么处理

    • 将公用的JS库通过script标签在index.html进行外部引入,减少我们打包出来的js文件的大小,让浏览器并行下载资源文件,提高下载速度
    • 在配置路由的时候进行路由的懒加载,在调用到改路由时再加载次路由相对应的js文件
    • 加一个首屏loading图或骨架屏,提高用户的体验
    • 尽可能使用CSS Sprites和字体图标库
    • 图片的懒加载等

    4. 从输入网址到网页渲染完成经历了什么

    1. 输入网址按回车键或点击跳转
    2. 发送到DNS服务器进行DNS解析,获取到我们对应web服务器对应的ip地址
    3. 与Web服务器建立TCP连接
    4. 浏览器向web服务器发送http请求
    5. Web服务器进行响应请求并返回指定的url数据(当然这里也可能是错误信息或者重定向到新的url地址等)
    6. 浏览器下载web服务器返回的数据及解析html源文件
    7. 根据文件生成DOM树和样式树合成我们的渲染树,解析js,最后渲染我们的页面然后显示出来

    5. 关于修改了数据,视图不更新的理解和处理方式

    1. Vue中给data中的对象属性添加一个新的属性时会发生什么

      经过打印发现数据是已经改变了,但是由于在Vue实例创建时, 新添加的属性并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局api——> $set()

      $set()使用方法:

      $set(需要修改的对象,“对象的属性”,值)

    <div id="app">
    	<ul>
    		<li v-for="(item,index) in obj" :key='index'>{{item}}</li>
    	</ul>
    	<button @click='add'>添加新属性d</button>
    </div>
    <script type="text/javascript" src="vue.js"></script>
    <script type="text/javascript">
    	new Vue({
    		el:'#app',
    		data(){
    			return {
    				obj:{
    					'a':'我是a',
    					'b':'我是b',
    					'c':'我是c',
    				}
    			}
    		},
    		methods:{
    			add(){
    				// this.obj.d='我是d'
    				this.$set(this.obj,'d','我是d')
    				console.log(this.obj)
    			}
    		}
    	})
    </script>
    

    6.在vue里面你如何做数据的监听

    1. watch里面监听
    • 第一种写法
      ​watch:{
        ​obj(newval,oldval){
        ​	console.log(newval,oldval)},
      }
    
    • 第二种写法可设置deep为true对数据进行深层遍历监听
    watch:{
       obj:{
        ​handler(newval,oldval){
        ​	console.log(222)
        ​	console.log(newval,oldval)},
        ​deep:true}
    }
    
    2. computed 里面监听
      - computed里面的依赖改变时,所计算的属性或作出事实的改变
    
    展开全文
  • vue常见面试题

    2021-01-07 04:40:30
    vue面试题汇集 vue面试题汇总二 vue面试总结三 vue面试题汇总四 vue面试题汇总五 vue面试题汇总六 axios是什么?怎么使用?描述使用它来实现登录功能的流程 1.axios是基于promise使用浏览器好node.js的一个http客服...
  • vue最新常见面试题

    2020-04-01 11:18:42
    这里写自定义目录标题vue.js核心思想新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右...
  • 2、怎么定义vue-router的动态路由?怎么获取传过来的动态参数? 答:在router目录下的index.js文件中,对path属性加上/:id, 获取传过来的动态参数通过使用router对象的params.id 3、vue-router有哪几种...
  • 关于vue常见面试题

    千次阅读 多人点赞 2018-09-22 14:28:07
    1.谈谈你对vue的认识 vue概念:是一个构建用户界面的渐进式框架,典型的MVVM框架。 注:模型(Model)只是普通的JavaScript对象,修改它则视图(View)会自动更新。这种设计让状态管理变得非常简单而直观。 vue...
  • 1.v-show和v-if指令的共同点和不同点? v-show本质就是通过控制css中的display设置为none,控制隐藏 v-if是动态的向DOM文档流内添加或者删除DOM元素 v-show是css切换,v-if是完整的...4.vue导航守卫(路由守卫)是什么
  • vue常见面试题

    2021-04-13 14:43:23
    vue常见面试题 1.vue优点? 答:轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb; 简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习; 双向数据绑定:保留了angular的特点,...
  • 简介VUE(常见面试题)

    2021-05-13 22:01:39
    什么是vue的生命周期? vue实例从创建到销毁的过程,就是生命周期。也就是从开始创建,初始化数据,编译模板,挂载DOM -》渲染,更新-》渲染,卸载等一些列过程。这是Vue的生命周期。 vue生命周期的作用是什么? 它...
  • 关于Vue常见面试题

    2018-12-03 15:00:00
    因此我们需要在 VueRouter 的参数中使用 children 配置,这样就可以很好的实现路由嵌套。 index.html,只有一个路由出口  id="app">  <!-- router-view 路由出口, 路由匹配到的组件将渲染在这里 -->  ...
  • Vue常见面试题

    2021-01-03 11:22:37
    下面来看常见面试题: 1、v-for和v-if哪个优先级更高?如果两者同时出现,应该怎么优化得到更好的性能? 源码位置:src/compiler/codegen/index.js 官方说法: 永远不要把 v-if 和 v-for 同时用在同一个元素上。...
  • VUE常见面试题

    2021-04-21 20:10:54
    VUE常见面试题 1.单页应用(SPA) •概念 ​ 单页应用(只有一个html文件,整个网站的所有内容都在这一个html里,通过js来处理)不仅仅是在页面交互是无刷新的,连页面跳转都是无刷新的。为了实现单页应用 ==> ...
  • VUE 常见面试题

    2021-04-26 14:35:24
    alive会增加哪两个生命周期vue中solt的使用方式,以及solt作用域插槽的用法为什么在组件内部data是一个函数而不是一个对象vue中动画如何实现浅谈对路由的理解路由跳转方式有哪几种路由传值的方式有哪几种路由配置项...
  • 汇总Vue常见面试题

    2018-12-06 11:37:15
    下面是是转载的一个面试题的总结,便于自己梳理和回看,大家可供参考。面试题的答案不是固定的,重在个人的理解和回答。 一. 请谈谈Vue中的MVVM模式 MVVM全称是Model-View-ViewModel Vue是以数据为驱动的,Vue...
  • Vue常见面试题汇总

    2019-02-22 10:19:00
    Vue框架常见面试题 1、active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-link组件。 2、怎么定义vue-router的动态路由?怎么获取传过来的动态参数? 答:在router目录下的...
  • vue 常见面试题

    2021-09-30 22:52:23
    1.vue生命周期 什么是Vue生命周期? Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期 Vue生命...
  • Vue常见面试题整理

    千次阅读 多人点赞 2018-09-20 09:48:45
    原文:Vue面试中,经常会被问到的面试题/Vue知识点整理 地址:https://segmentfault.com/a/1190000016344599 作者:沉静地闪光 本文经授权转载,仅用于学习,版权归原作者所有。 看看面试题,只是为了查漏补缺,看...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,881
精华内容 1,152
关键字:

vue路由常见面试题

vue 订阅