VUE面试总结

1、组件间怎么传值,具体说说代码怎样实现

  • 子传父:子向父是通过 events($emit);通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners

  • 父传子:父向子传递数据是通过 props,

  • 兄弟组件传值:bus,vuex

  • 跨级父子通信:Bus;Vuex;provide / inject API、$attrs/$listeners

以上传值示列文档

2、Vue双向绑定原理

采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者 2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数 3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

3、Vue的生命周期和钩子函数

image.png

beforecreate : 举个栗子:可以在这加个loading事件 created :在这结束loading,还做一些初始化,实现函数自执行 mounted : 在这发起后端请求,拿回数据,配合路由钩子做一些事情 beforeDestroy: 你确认删除XX吗? destroyed :当前组件已被删除,清空相关内容

4、应该在vue的生命周期的什么阶段发出ajax请求,为什么

看实际情况,一般在 created 里面就可以,如果涉及到需要页面加载完成之后的话就用 mounted

5、vuex是什么?怎么使用?哪种功能场景使用它?

只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事务; 异步逻辑应该封装在action中。 在main.js引入store,注入。新建了一个目录store,….. export 。 场景有:单页应用中,组件之间的状态同步、音乐播放、登录状态、加入购物车


image.png

state Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters 类似vue的计算属性,主要用来过滤一些数据。
action actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。

const store = new Vuex.Store({ //store实例
      state: {
         count: 0
             },
      mutations: {                
         increment (state) {
          state.count++
         }
          },
      actions: { 
         increment (context) {
          context.commit('increment')
   }
 }
})

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
})

6、Vue路由守卫

路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。对此,vue-route 提供的 beforeRouteUpdate 可以方便地实现导航守卫。

全局守卫

你可以使用 router.beforeEach 注册一个全局前置守卫:

const router = new VueRouter({ ... })
​
router.beforeEach((to, from, next) => {
 // ...
})

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象

  • from: Route: 当前导航正要离开的路由

  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数,确保要调用 next 方法,否则钩子就不会被 resolved

举一个例子:

  1. 列举需要判断登录状态的“路由集合”,当跳转至集合中的路由时,如果“未登录状态”,则跳转到登录页面LoginPage;

  2. 当直接进入登录页面LoginPage时,如果“已登录状态”,则跳转到首页HomePage;

7、常用的vue指令,Vue的自定义指令怎么做

常用的vue指令有v-if、v-show,v-for,v-model等等

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

8、Vue登录流程?需要做什么验证

在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下:

  • 第一次登录的时候,前端调后端的登陆接口,发送用户名和密码

  • 后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token

  • 前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面

  • 前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面

  • 每次调后端接口,都要在请求头中加token,我们常用axios的请求库中,添加全局拦截器,将token设置在请求头中。

  • 后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401

  • 如果前端拿到状态码为401,就清除token信息并跳转到登录页面

// http request 拦截器
axios.interceptors.request.use(
    config => {
        if (store.state.token) {  // 判断是否存在token,如果存在的话,则每个http header都加上token
            config.headers.Authorization = `token ${store.state.token}`;
        }
        return config;
    },
    err => {
        return Promise.reject(err);
    });
 
// http response 拦截器
axios.interceptors.response.use(
    response => {
        return response;
    },
    error => {
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    // 返回 401 清除token信息并跳转到登录页面
                    store.commit(types.LOGOUT);
                    router.replace({
                        path: 'login',
                        query: {redirect: router.currentRoute.fullPath}
                    })
            }
        }
        return Promise.reject(error.response.data)   // 返回接口返回的错误信息
});


9、讲一下MVVM中的vm工作流程

MVVM 是 Model-View-ViewModel 的缩写。
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View 代表UI 组件,它负责将数据模型转化成UI 展现出来。 ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。 在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

10、Vue和react的区别?

  • react和vue都是做组件化的,整体的功能都类似,但是他们的设计思路是有很多不同的。使用react和vue,主要是理解他们的设计思路的不同

  • react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流,

  • 而vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom

  • react的性能优化需要手动去做,而vue的性能优化是自动的,但是vue的响应式机制也有问题,就是当state特别多的时候,Watcher也会很多,会导致卡顿

  • react是类式的写法,api很少,而vue是声明式的写法,通过传入各种options,api和参数都很多

  • react可以通过高阶组件(Higher Order Components--HOC)来扩展,而vue需要通过mixins来扩展

总结:react整体的思路就是函数式,所以推崇纯组件,数据不可变,单向数据流,当然需要双向的地方也可以做到,比如结合redux-form,而vue是基于可变数据的,支持双向绑定。react组件的扩展一般是通过高阶组件,而vue组件会使用mixin。vue内置了很多功能,而react做的很少,很多都是由社区来完成的,vue追求的是开发的简单,而react更在乎方式是否正确。

11、Vue里面的插槽

<slot>

是组件的一块HTML模板,父组件决定这块模板显不显示以及怎么显示。

位置由子组件自身决定(slot现在组件template的什么位置,父组件传过来的模板将来就显示在什么位置)

匿名插槽:只能有一个,可以放在组件的任何位置

<v-xx><h1></h1></v-xx>

12、Vue-cli2.0和Vue-cli3.0的区别

用vue-cli3.0版本创建的项目与2.0版本相比较,我们会发现,文件目录少了很多 eg:build、config,那么如何像vue-cli 2.* 之前关于端口号的配置、打包之后的路径的配置、图片的配置等,到哪里配置呢??vue-cli 3.0 可以在项目的根目录下新建一个 vue.config.js 文件,之前繁琐的配置都可以在这里直接配置

3.0能直接运行单个组件

3.0有一个UI管理界面

安装了2.0版本,要先卸载

13、Vue的路由实现 || vue-router的原理

hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取; 特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。 history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

14、vue路由的钩子函数

首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。
​
beforeEach主要有3个参数to,from,next:
​
to:route即将进入的目标路由对象,
​
from:route当前导航正要离开的路由
​
next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。

15、对keep-alive 的了解

<keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

<keep-alive><transition>相似,只是一个抽象组件,它不会在DOM树中渲染(真实或者虚拟都不会),也不在父组件链中存在,比如:你永远在 this.$parent 中找不到 keep-alive

keep-alive生命周期钩子函数:activated、deactivated

使用<keep-alive>会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在activated阶段获取数据,承担原来created钩子中获取数据的任务。

被包含在 <keep-alive> 中创建的组件,会多出两个生命周期的钩子: activateddeactivated

activated:在组件被激活时调用,在组件第一次渲染时也会被调用,之后每次keep-alive激活时被调用。

deactivated:在组件被停用时调用。

注意:只有组件被 keep-alive 包裹时,这两个生命周期才会被调用,如果作为正常组件使用,是不会被调用,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子依然不会被调用!另外在服务端渲染时此钩子也不会被调用的。

什么时候获取数据?

当引入keep-alive 的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。

16、DOM 和虚拟DOM的区别 以及你对于他们了解

DOM的本质:DOM是浏览器概念,浏览器从服务器端读取html页面,浏览器将html解析成一棵元素嵌套关系的dom树,用对象来表示页面上的元素,并提供操作dom对象的api。

虚拟DOM:框架概念,程序员用js对象来模拟页面上dom元素的嵌套关系( 本质 ),为了实现页面元素的高效更新( 目的 )

虚拟DOM是真实DOM结构的映射,即一个数据集合

// 对于这个Html 文件
<div class="">
    <p>
        <span>
            Hello, the world!
        </span>
        <span>
            Hello, the code!
        </span>
    </p>

</div>

// 它对应的虚拟DOM就是
let nodesData = {
    tag: 'div',
    attr: []
    children: [
      {
        tag: 'p',
        children: [
          {
            tag: 'span',
            children: [
              {
                tag: '#text',
                text: 'Hello, the world!'
              }
            ]
          }
        ]
      },
      {
        tag: 'span',
          children: [
            {
              tag: '#text',
              text: 'Hello, the code!'
            }
          ]
      }
    ]
  }
 //  或这种写法
 let vNodes = v('div', [
      v('p', [
        v('span', [ v('#text', 'Hello, the world!') ] )
        ]
      ),
      v('span', [
        v('#text',  'Hello, the code!')
        ])
    ]
  )
 虚拟DOM的核心就是一个diff算法:使用一个render()方法就可以将上面vNodes还原成真实的Html页面

17、vue指令的生命周期

自定义指令有五个生命周期(也叫钩子函数),分别是 bind,inserted,update,componentUpdated,unbind

  • bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。

  • inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。

  • update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。

  • componentUpdated:被绑定元素所在模板完成一次更新周期时调用。

  • unbind:只调用一次,指令与元素解绑时调用。

18、vue封装公共组件(通用组件)需要考虑到什么

开发通用组件是很基础且重要的工作,通用组件必须具备高性能、低耦合的特性

一、数据从父组件传入

为了解耦,子组件本身就不能生成数据。即使生成了,也只能在组件内部运作,不能传递出去。

父对子传参,就需要用到 props,但是通用组件的的应用场景比较复杂,对 props 传递的参数应该添加一些验证规则

二、在父组件处理事件

在通用组件中,通常会需要有各种事件,

比如复选框的 change 事件,或者组件中某个按钮的 click 事件

这些事件的处理方法应当尽量放到父组件中,通用组件本身只作为一个中转

三、记得留一个 slot

一个通用组件,往往不能够完美的适应所有应用场景

所以在封装组件的时候,只需要完成组件 80% 的功能,剩下的 20% 让父组件通过 solt 解决

四、不要依赖 Vuex

父子组件之间是通过 props 和 自定义事件 来传参,非父子组件通常会采用 Vuex 传参

但是 Vuex 的设计初衷是用来管理组件状态,虽然可以用来传参,但并不推荐

因为 Vuex 类似于一个全局变量,会一直占用内存

在写入数据庞大的 state 的时候,就会产生内存泄露

五、合理运用 scoped 编写 CSS

在编写组件的时候,可以在 <style> 标签中添加 scoped,让标签中的样式只对当前组件生效

但是一味的使用 scoped,肯定会产生大量的重复代码

所以在开发的时候,应该避免在组件中写样式

当全局样式写好之后,再针对每个组件,通过 scoped 属性添加组件样式

19、父组件怎么调用子组件里的方法

  • 在父组件中:首先要引入子组件 import Child from './child';

  • <child ref="mychild"></child>是在父组件中为子组件添加一个占位,ref="mychild"是子组件在父组件中的名字

  • 父组件中 components: {  是声明子组件在父组件中的名字}

  • 在父组件的方法中调用子组件的方法,很重要 this.$refs.mychild.parentHandleclick("嘿嘿嘿"); parentHandleclick是子组件中的方法

20、css只在当前组件起作用

答:在style标签中写入scoped即可 例如:<style scoped></style>

21、v-if 和 v-show 区别

答:v-if按照条件是否渲染,v-show是display的block或none;

22、route和router的区别

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

23、vue.js的两个核心是什么?

答:数据驱动、组件系统

24、vue常用的修饰符?

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

25、v-on 可以绑定多个方法吗?

答:可以

26、vue中 key 值的作用?

答:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。

27、什么是vue的计算属性?

答:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。

计算属性就是当其依赖属性的值发生变化时,这个属性的值会自动更新。
<body>
    <div id="app">
         <input type="text" v-model="msg">
         <p>原始字符:{{msg}}</p>
         <p>计算属性翻转字符:{{reverseMsg}}</p>
    </div>
    <script>
         new Vue({
             el:'#app',
             data:{
                 msg:'Hello'
             },
             //vue的计算属性
             computed:{
                 reverseMsg(){
                     //返回翻转后的字符串,当msg变化后reverseMsg会跟着变化
                     return this.msg.split('').reverse().join('')
                 }
             }
         })
    </script>
</body>

28、vue等单页面应用及其优缺点

答:优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。 缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。

29、路由之间跳转

声明式(标签跳转) 编程式( js跳转)

通过router-link实现跳转

img

通过js的编程的方式

img

30、Vue中怎么实现跨域

使用http-proxy-middleware 代理解决(项目使用vue-cli脚手架搭建)

例如请求的url:“http://aa.com/demo.json“

1、打开config/index.js,在proxyTable中添写如下代码:

proxyTable: { 
  '/api': {  //使用"/api"来代替"http://aa.com" 
    target: 'http://aa.com', //源地址 
    changeOrigin: true, //改变源 
    secure:false // 是否使用https
    pathRewrite: { 
      '^/api': '/api' //路径重写 
      } 
  } 

2、使用axios请求数据时直接使用“/api”

getData () { 
 axios.get('/api/demo.json', function (res) { 
   console.log(res) 
})

以上配置只是在开发环境(dev)中解决跨域。要解决生产环境的跨域问题,则在config/dev.env.jsconfig/prod.env.js里也就是开发/生产环境下分别配置一下请求的地址API_HOST,开发环境中我们用上面配置的代理地址api,生产环境下用正常的接口地址

module.exports = merge(prodEnv, {
 NODE_ENV: '"development"',
 API_HOST:"/api/"
})
'use strict'
module.exports = {
 NODE_ENV: '"production"',
 API_HOST:"http://aa.com"
}

31、Vue首屏加载过慢的解决方法有哪些

vue首屏加载过慢的原因

  • 网速慢肯定会导致首屏加载过慢,但是在这里我们不做讨论

  • vue项目作为一个单页面应用,如果不对路由进行处理,在加载首页的时候,就会将所有组件全部加载,并向服务器请求数据,这必将拖慢加载速度;

  • 通过查看Network,发现整个网站加载试讲长达10几秒,加载时间最长的就是js、css文件和媒体文件及图片

解决方案

  • vue-router 路由懒加载

  • 在项目开发中,我们会用到很多第三方库,如果可以按需引入,我们可以只引入自己需要的组件,来减少所占空间,但也会有一些不能按需引入,我们可以采用CDN外部加载,在index.html中从CDN引入组件,去掉其他页面的组件import,

  • 关闭sourcemap,sourcemap是为了方便线上调试用的,因为线上代码都是压缩过的,导致调试极为不便,而有了sourcemap,就等于加了个索引字典,出了问题可以定位到源代码的位置。 但是,这个玩意是每个js都带一个sourcemap,有时sourcemap会很大,拖累了整个项目加载速度,为了节省加载时间,我们将其关闭掉

  • 开启gzip压缩,这个优化是两方面的,前端将文件打包成.gz文件,然后通过nginx的配置,让浏览器直接解析.gz文件。

  • 加个loading效果:首页加个好看的loading阻塞一下,让用户别等的那么心焦。

  • 如果首页真的有瓶颈,可以考虑用node单独做服务端渲染,而下面的子页面仍用spa单页的方式交互。

32、vue如何实现按需加载组件

https://www.cnblogs.com/-roc/p/9983177.html

33、 请说下封装 vue 插件封装过程

https://www.jb51.net/article/157120.htm

34、vue项目的多语言处理

Vue已经有了这个多语种的插件,vue-i18n

35、vue中的watch介绍和场景

监听并处理data属性的更新,对data属性的监听,说明属性是在data中声明过的 属性更新时调用监听函数,可选参数分别为新值和旧值,对属性重新设置值,只要跟原来的值相等就不会触发函数调用,这一点跟计算属性是相似的,

// 基础用法
watch: {
 activeTab(newValue, oldValue) {
 console.log(newValue, oldValue);
 this.getList();
 }
}
// 函数体调用Vue实例的方法可简写
watch: {
 activeTab: 'getList'
}

属性初始化的值默认不会触发监听,解决办法添加说明immediate:true,表示监听初始值,此时使用handler写法

// 基础用法
watch: {
        activeTab(newValue, oldValue) {
            console.log(newValue, oldValue);
            this.getList();
        }
}
// 函数体调用Vue实例的方法可简写
watch: {
        activeTab: 'getList'
}

当被监听的属性为对象时,默认不会监听对象内部属性的变化,而是只监听属性被赋值时的变化,解决办法添加说明deep:true(默认为false),此时监听器会深度遍历给对象的每一个属性都带上监听器,更新写法

// 监听对象的所有属性
// 监听对象的所有属性
watch: {
        activeTab: {
            handler(newValue, oldValue) {
                console.log(newValue, oldValue);
                this.getList();
            },
            // 深度监听
            deep: true
        }
    }
// 监听对象的某些属性
watch: {
        'activeTab.index': {
            handler(newValue, oldValue) {
                console.log(newValue, oldValue);
                this.getList();
            }
        }
    }

另外组件中的监听器会随组建的注销而注销,不会造成内存溢出,但如果使用命令式的( vm.$watch)全局的监听器需要手动注销才行

推荐阅读更多精彩内容

  • vue双向绑定的原理(详细链接) VUE实现双向数据绑定的原理就是利用了 Object.definePropert...
    Smallbore阅读 493评论 0 8
  • 请详细说下你对vue生命周期的理解? beforeCreate(创建前) 在数据观测和初始化事件还未开始 crea...
    阿喜liang阅读 165评论 0 1
  • 1. Vue.js介绍 Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API; V...
    MC阿十三阅读 556评论 3 9
  • 1.Vue的数据双向绑定如何实现?Vue的数据双向绑定如何实现? v-model指令或者.sync修饰 2.Vue...
    骑着蜗牛逛妓院阅读 2,142评论 1 9
  • 前言 接上篇前端Js笔试题面试题,收集整理Vue相关的面试题,供自己现在和以后学习和面试,也希望能对点进来的小伙伴...
    蛙哇阅读 511评论 0 8