35 道常见前端 Vue 面试题详解
1、请讲述下 Vue 的 MVVM 的理解? MVVM 是 Model-View-ViewModel 的缩写,即将数据模型与数据表现层通过数据驱动进行分离,从而只需要关注数据模型的开发,而不需要考虑页面的表现,具体说来如下: **Model** 代表数据模型:主要用于定义数据和操作的业务逻辑。 **View** 代表页面展示组件(即 DOM 展现形式):负责将数据模型转化成 UI 展现出来。 **…

1、请讲述下 Vue 的 MVVM 的理解? MVVM 是 Model-View-ViewModel 的缩写,即将数据模型与数据表现层通过数据驱动进行分离,从而只需要关注数据模型的开发,而不需要考虑页面的表现,具体说来如下: **Model** 代表数据模型:主要用于定义数据和操作的业务逻辑。 **View** 代表页面展示组件(即 DOM 展现形式):负责将数据模型转化成 UI 展现出来。 **…

MVVM 是 Model-View-ViewModel 的缩写,即将数据模型与数据表现层通过数据驱动进行分离,从而只需要关注数据模型的开发,而不需要考虑页面的表现,具体说来如下:
Model 代表数据模型:主要用于定义数据和操作的业务逻辑。
View 代表页面展示组件(即 DOM 展现形式):负责将数据模型转化成 UI 展现出来。
ViewModel 为 Model 和 View 之间的桥梁:监听模型数据的改变和控制视图行为、处理用户交互。通过双向数据绑定把 View 层和 Model 层连接了起来,而 View 和 Model 之间的同步工作完全是自动的,无需人为干涉。
在 MVVM 架构下,View 和 Model 之间并没有直接的联系,而是通过 ViewModel 进行交互,Model 和 ViewModel 之间的交互是双向的,因此 View 数据的变化会同步到 Model 中,而 Model 数据的变化也会立即反应到 View 上。
答:总共分为 8 个阶段,具体为:创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后:在 beforeCreated 阶段,Vue 实例的挂载元素 el 和数据对象 data 都为 undefined,还未初始化;在 created 阶段,Vue 实例的数据对象 data 有了,但 el 还没有挂载。
载入前/后:在 beforeMount 阶段,Vue 实例的 $el 和 data 都初始化了,但还是挂载之前为虚拟的 DOM 节点,data.message 还未替换;在 mounted 阶段,Vue 实例挂载完成,data.message 成功渲染。
更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。
销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 Vue 实例已经解除了事件监听以及和 DOM 的绑定,但是 DOM 结构依然存在。
beforeCreate:在 new 一个 Vue 实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建,data 和 methods 中的数据都还没有初始化。不能在这个阶段使用 data 中的数据和 methods 中的方法。
created:data 和 methods 都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作。
beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的,不能直接操作页面的 DOM 和获取 DOM 对象。
mounted:执行到这个钩子的时候,就表示 Vue 实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。如果我们想要通过插件操作页面上的 DOM 节点,最早可以在这个阶段中进行。
beforeUpdate:当执行这个钩子时,页面中的显示的数据还是旧的,data 中的数据是更新后的,页面还没有和最新的数据保持同步。
updated:页面显示的数据和 data 中的数据已经保持同步了,都是最新的。
beforeDestroy:Vue 实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods、指令、过滤器……都是处于可用状态。还没有真正被销毁。
destroyed:这个时候上所有的 data 和 methods、指令、过滤器……都是处于不可用状态。组件已经被销毁了。
共同点:都能控制元素的显示和隐藏;
不同点:实现本质方法不同,v-show 本质就是通过控制 CSS 中的 display 设置为 none,控制隐藏,只会编译一次;v-if 是动态的向 DOM 树内添加或者删除 DOM 元素,若初始值为 false,就不会编译了。而且 v-if 不停的销毁和创建比较消耗性能。
如果要频繁切换某节点,使用 v-show(切换开销比较小,初始开销较大)。如果不需要频繁切换某节点使用 v-if(初始渲染开销较小,切换开销比较大)。
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,这意味着 v-if 将分别重复运行于每个 v-for 循环中。 所以,不推荐 v-if 和 v-for 同时使用。如果 v-if 和 v-for 一起用的话,Vue 中会自动提示 v-if 应该放到外层去。
需要使用 key 来给每个节点做一个唯一标识,Diff 算法就可以正确的识别此节点。主要是为了高效的更新虚拟 DOM。
⚠️:v- 会转化为对应的 transition 的 name 值。
{enter:1000, leave:300}。自定义指令分为全局指令和组件指令,其中全局指令需要使用 directive 来进行定义,组件指令需要使用 directives 来进行定义,具体定义方法同过滤器 filter 或者其他生命周期,具体使用方法如下:
全局自定义指令 directive(name, {}),其中 name 表示定义的指令名称(定义指令的时候不需要带 v-,但是在调用的时候需要带 v-),第二个参数是一个对象,对象中包括五个自定义组件的钩子函数,具体包括:
钩子函数对应的参数 el, binding, vnode, oldVnode,具体参数讲解如下:
a. el:指令所绑定的元素,可以直接操作 DOM 元素。
b. binding:一个对象,具体包括以下属性:
1. name:定义的指令名称,不包括 v-。
2. value:指令的绑定值,如果绑定的是一个计算式,value 为对应计算结果。
3. oldValue:指令绑定元素的前一个值,只对 update 和 componentUpdated 钩子函数有值。
4. expression:指令绑定的原始值,不对值进行任何加工。
5. arg:传递给指令的参数。
6. modifiers:指令修饰符,如:v-focus.show.async 则接收的 modifiers 为 {show: true, async: true}。
c. vnode:Vue 编译生成的虚拟 DOM。
d. oldVnode:上一个 vnode,只在 update 和 componentUpdated 钩子函数中有效。
⚠️:如果不需要其他钩子函数,可以直接简写为:directive("focus", function(el, binding){})。
Vue.js 是采用数据劫持结合发布者 - 订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter。 这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
第二步:compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。
第三步:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情是:
第四步:MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化 (input) -> 数据 model 变更的双向绑定效果。
3)具体过程详解:
a. 在采用 diff 算法进行新旧节点进行比较的时候,比较是按照在同级进行比较的,不会进行跨级比较。 b. 当数据发生改变的时候,set 方法会调用 dep.notify 通知所有的订阅者 watcher,订阅者会调用 patch 函数给响应的 DOM 进行打补丁,从而更新真实的视图。 c. patch 函数接受两个参数,第一个是旧节点,第二个是新节点,首先判断两个节点是否值得比较,值得比较则执行 patchVnode 函数,不值得比较则直接将旧节点替换为新节点。如果两个节点一样就直接检查对应的子节点,如果子节点不一样就说明整个子节点全部改变不再往下对比直接进行新旧节点的整体替换。 d. patchVnode 函数:找到真实的 DOM 元素;判断新旧节点是否指向同一个对象,如果是就直接返回;如果新旧节点都有文本节点,那么直接将新的文本节点赋值给 DOM 元素并且更新旧的节点为新的节点;如果旧节点有子节点而新节点没有,则直接删除 DOM 元素中的子节点;如果旧节点没有子节点,新节点有子节点,那么直接将新节点中的子节点更新到 DOM 中;如果两者都有子节点,那么继续调用函数 updateChildren。 e. updateChildren 函数:抽离出新旧节点的所有子节点,并且设置新旧节点的开始指针和结束指针,然后进行两两比较,从而更新 DOM(调整顺序或者插入新的内容,结束后删掉多余的内容)。
传递参数可以使用 props,传递函数可以直接在调用子组件的时候传递自定义事件,并使用 $emit 来调用,例如:
// 父组件
<div class="parent">
<child @getinfo="myname" :userinfo="usermessage"></child>
<div>{{ myname }}</div>
</div>
export default {
data() {
return {
usermessage: '我是父亲'
}
},
methods: {
myname(name) {
console.log('我的名字叫' + name)
}
}
}
// 子组件
<div class="child">
来源:{{ userinfo }}
<button @click="getname">显示我的名字</button>
</div>
export default {
props: ['userinfo'],
methods: {
getname() {
this.$emit('getinfo', 'bilibili')
}
}
}
首先建立一个 Vue 实例空白页(js 文件):
import Vue from 'vue'
export default new Vue()
组件 A(数据发送方)通过使用 $emit 自定义事件把数据带过去:
<template>
<div>
<span>A 组件->{{msg}}</span>
<input type="button" value="把 a 组件数据传给 b" @click="send">
</div>
</template>
<script>
import vmson from "../../../util/emptyVue"
export default {
data() {
return {
msg: { a: '111', b: '222' }
}
},
methods: {
send: function() {
vmson.$emit("aevent", this.msg)
}
}
}
</script>
组件 B(数据接收方)使用而通过 $on 监听自定义事件的 callback 接收数据:
<template>
<div>
<span>b 组件,a 传的数据为->{{msg}}</span>
</div>
</template>
<script>
import vmson from "../../../util/emptyVue"
export default {
data() {
return {
msg: ""
}
},
mounted() {
vmson.$on("aevent", (val) => {
// 监听事件 aevent,回调函数要使用箭头函数
console.log(val) // 打印结果:我是 a 组件的数据
this.msg = val
})
}
}
</script>
在浏览器中符号'#',#以及#后面的字符称之为 hash,用 window.location.hash 读取;
特点:hash 虽然在 URL 中,但不被包括在 HTTP 请求中;用来指导浏览器动作,对服务端安全无用,hash 不会重加载页面。
history 采用 HTML5 的新特性;
提供了两个新方法:pushState(), replaceState() 可以对浏览器历史记录栈进行修改,以及 popState 事件的监听到状态变更。history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,否则会报 404 错误。
相同点: React 采用特殊的 JSX 语法,Vue.js 在组件开发中也推崇编写 .vue 特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数 AJAX,Route 等功能到核心包,而是以插件的方式加载;在组件开发中都支持 mixins 的特性。
不同点: React 采用的 Virtual DOM 会对渲染出来的结果做脏检查;Vue.js 在模板中提供了指令,过滤器等,可以非常方便,快捷地操作 Virtual DOM。
相同点: 都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。
不同点: AngularJS 的学习成本高,比如增加了 Dependency Injection 特性,而 Vue.js 本身提供的 API 都比较简单、直观;在性能上,AngularJS 依赖对数据做脏检查,所以 Watcher 越多越慢;Vue.js 使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。
Vue 路由钩子大致可以分为三类:
主要包括 beforeEach 和 afterEach,beforeEach 函数有三个参数:
afterEach 函数不用传 next() 函数。这类钩子主要作用于全局,一般用来判断权限,以及以及页面丢失时候需要执行的操作,例如:
// 使用钩子函数对路由进行权限跳转
router.beforeEach((to, from, next) => {
const role = localStorage.getItem('ms_username');
if (!role && to.path !== '/login') {
next('/login');
} else if (to.meta.permission) {
// 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已
role === 'admin' ? next() : next('/403');
} else {
// 简单的判断 IE10 及以下不进入富文本编辑器,该组件不兼容
if (navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor') {
Vue.prototype.$alert('vue-quill-editor 组件不兼容 IE10 及以下浏览器,请使用更高版本的浏览器查看', '浏览器不兼容通知', {
confirmButtonText: '确定'
});
} else {
next();
}
}
})
主要用于写某个指定路由跳转时需要执行的逻辑。
主要包括 beforeRouteEnter 和 beforeRouteUpdate, beforeRouteLeave,这几个钩子都是写在组件里面也可以传三个参数 (to, from, next),作用与前面类似。
beforeRouteEnter(to, from, next) {
next(vm => {
if (vm.$route.meta.hasOwnProperty('auth_key') && vm.$route.meta.auth_key != '') {
if (!vm.hasPermission(vm.$route.meta.auth_key)) {
vm.$router.replace('/admin/noPermission')
}
}
})
}
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,具体包括:
Vue.filter('testfilter', function (value, text) {
// 返回处理后的值
return value + text
})
filters: {
changemsg: (val, text) => {
return val + text
}
}
<h3 :title="test|changemsg(1234)">{{test|changemsg(4567)}}</h3>
<!-- 多个过滤器也可以串行使用 -->
<h2>{{name|filter1|filter2|filter3}}</h2>
// 1. 创建一个单独的文件定义并暴露函数对象
const filter1 = function (val) { return val + '--1' }
const filter2 = function (val) { return val + '--2' }
const filter3 = function (val) { return val + '--3' }
export default {
filter1, filter2, filter3
}
// 2. 导入 main.js(在 Vue 实例之前)
import filters from './filter/filter.js'
// 3. 循环注册过滤器
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染,页面第一次进入,钩子的触发顺序:created -> mounted -> activated,退出时触发 deactivated,当再次进入(前进或者后退)时,只触发 activated 事件。挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中;其有几个属性如下:
<!-- 逗号分隔字符串,只有组件 a 与 b 被缓存。-->
<keep-alive include="a,b">
<component></component>
</keep-alive>
<!-- 正则表达式 (需要使用 v-bind,符合匹配规则的都会被缓存) -->
<keep-alive :include="/a|b/">
<component></component>
</keep-alive>
<!-- Array (需要使用 v-bind,被包含的都会被缓存) -->
<keep-alive :include="['a', 'b']">
<component></component>
</keep-alive>
根据业务需求,建立组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑。
准备好组件的数据输入。即分析好逻辑,定好 props 里面的数据、类型。 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法。 封装完毕了,直接调用即可。
plugins: [
new webpack.optimize.UglifyJsPlugin({
// 添加 - 删除 console.log
compress: {
warnings: false,
drop_debugger: true,
drop_console: true
},
sourceMap: true
})
]
http {
// 在 http 中配置如下代码,
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 8; # 压缩级别
gzip_buffers 16 8k; #gzip_http_version 1.1;
gzip_min_length 100; # 不压缩临界值
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
}
使用 v-cloak 指令设置样式,这些样式会在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除。
一般用于解决网页闪屏的问题,在对一个的标签中使用 v-cloak,然后在样式中设置 [v-cloak] 样式,[v-cloak] 需写在 link 引入的 CSS 中,或者写一个内联 CSS 样式,写在 import 引入的 CSS 中不起作用。
答:就是先转化成 AST 树,再得到的 render 函数返回 VNode(Vue 的虚拟 DOM 节点),具体为:
首先,通过 compile 编译器把 template 编译成 AST 语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile 是 createCompiler 的返回值,createCompiler 是用以创建编译器的。
另外 compile 还负责合并 option。
然后,AST 会经过 generate(将 AST 语法树转化成 render function 字符串的过程)得到 render 函数,render 的返回值是 VNode,VNode 是 Vue 的虚拟 DOM 节点,里面有(标签名、子节点、文本等等)。
答:v-model 用于表单数据的双向绑定,其实它就是一个语法糖,这个背后就做了两个操作:
答:在 Vue 中理解修改数据后,对应的 DOM 需要一定的时间进行更新,因此为了能够准确的获取更新后的 DOM,可以采用延迟回调的方法进行更新 DOM 的获取,所以出现了 $nextTick 来进行延迟回调。即:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
答:这是有 JavaScript 的特性所导致,在 component 中,data 必须以函数的形式存在,不可以是对象。
组件中的 data 写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的 data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个 data,这样改一个全都改了。
通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于 PC 端。
指一个应用中有多个页面,页面跳转时是整页刷新。
用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点 SPA 对服务器压力较小;前后端分离;页面效果会比较炫酷(比如切换页面内容时的专场动画)。
不利于 SEO;导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理);初次加载时耗时多;页面复杂度提高很多。
答:push();pop();shift();unshift();splice();sort();reverse()。
router 是 VueRouter 的一个对象,通过 Vue.use(VueRouter) 和 VueRouter 构造函数得到一个 router 的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性,常见的有:
// 字符串
this.$router.push('home')
// 对象
this.$router.push({ path: 'home' })
// 命名的路由
this.$router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=123
this.$router.push({ path: 'register', query: { plan: '123' }})
// 页面路由跳转 前进或者后退
this.$router.go(-1) // 后退
$route 对象表示当前的路由信息,包含了当前 URL 解析得到的信息。包含当前的路径、参数、query 对象等。
Vue 异步组件技术 === 异步加载 Vue-Router 配置路由,使用 Vue 的异步组件技术,可以实现按需加载。但是,这种情况下一个组件生成一个 JS 文件。
/* Vue 异步组件技术 */
{
path: '/home', name: 'home', component: resolve => require(['@/components/home'], resolve)
},
{
path: '/index', name: 'Index', component: resolve => require(['@/components/index'], resolve)
},
{
path: '/about', name: 'about', component: resolve => require(['@/components/about'], resolve)
}
路由懒加载 (使用 import)
// 下面 2 行代码,没有指定 webpackChunkName,每个组件打包成一个 JS 文件。
/*
const Home = () => import('@/components/home')
const Index = () => import('@/components/index')
const About = () => import('@/components/about')
*/
// 下面 2 行代码,指定了相同的 webpackChunkName,会合并打包成一个 JS 文件。把组件按组分块
const Home = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home')
const Index = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/index')
const About = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/about')
{
path: '/about', component: About
},
{
path: '/index', component: Index
},
{
path: '/home', component: Home
}
Vue-Router 配置路由,使用 Webpack 的 require.ensure 技术,也可以实现按需加载。这种情况下,多个路由指定相同的 chunkName,会合并打包成一个 JS 文件。
/* 组件懒加载方案三:Webpack 提供的 require.ensure() */
{
path: '/home', name: 'home', component: r => require.ensure([], () => r(require('@/components/home')), 'demo')
},
{
path: '/index', name: 'Index', component: r => require.ensure([], () => r(require('@/components/index')), 'demo')
},
{
path: '/about', name: 'about', component: r => require.ensure([], () => r(require('@/components/about')), 'demo-01')
}
答:delete 只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。Vue.delete 直接删除了数组 改变了数组的键值。
使用 location.href='/url' 来跳转,简单方便,但是刷新了页面; 使用路由方式跳转,无刷新页面,静态跳转;
在子组件内使用特殊的 <slot> 元素就可以为这个子组件开启一个 slot(插槽),在父组件模板里,插入在子组件标签内的所有内容将替代子组件的 <slot> 标签及它的内容。
简单说来就是:在子组件内部用 <slot> 标签占位,当在父组件中使用子组件的时候,我们可以在子组件中插入内容,而这些插入的内容则会替换 <slot> 标签的位置。
当然:单个 slot 的时候可以不对 slot 进行命名,如果存在多个 则一个可以不命名,其他必须命名,在调用的时候指定名称的对应替换 slot,没有指定的则直接默认无名称的 slot。
触发当前实例上的自定义事件(并将附加参数都传给监听器回调)。
监听实例上自定义事件并调用回调函数,监听 emit 触发的事件。
监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器。
用来移除自定义事件监听器。如果没有提供参数,则移除所有的事件监听器;如果只提供了事件,则移除该事件所有的监听器;如果同时提供了事件与回调,则只移除这个回调的监听器。
这四个方法的实现原理是:通过对 Vue 实例挂载,然后分别使用对象存储数组对应的函数事件,其中 emit 通过循环查找存储的数组中对应的函数进行调用,once 只匹配一次就结束,on 是将对应的函数存储到数组中,off 是删除数组中指定的元素或者所有的元素事件。
可以用来获取 Vue 的根实例,比如在简单的项目中将公共数据放在 Vue 根实例上 (可以理解为一个全局 store),因此可以代替 Vuex 实现状态管理;
在子组件上使用 ref 特性后,this.$refs 属性可以直接访问该子组件。可以代替事件 emit 和 $on 的作用。
使用方式是通过 ref 特性为这个子组件赋予一个 ID 引用,再通过 this.$refs.testId 获取指定元素。
注意:$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的'逃生舱'——你应该避免在模板或计算属性中访问 refs。
$parent 属性可以用来从一个子组件访问父组件的实例,可以替代将数据以 prop 的方式传入子组件的方式;当变更父级组件的数据的时候,容易造成调试和理解难度增加;
答:在编写样式中,如果需要防止样式的污染,可以使用两种方式,一种是在组件的根元素上增加一个唯一的 class 或者 id,然后在编写组件的样式时候在根元素对应的 class 或者 id 下进行编写;另一种方式是在对应的 style 上添加 scoped 关键字,不过该关键字对引用的框架 UI 无效。
答:不起作用的原因是因为转码编译的问题,可以使用 babel 来进行处理,安装 babel polyfill 插件解决。
答:这是因为 Vue 还没有解析的情况下会容易出现花屏现象,看到类似于 {{data}} 的字样,可以使用两种方式来进行处理,一种为:在设置 index.html 的根元素的元素的样式为 display:none,然后在 mounted 中的 $nextTick 函数中 display:block 展示;另一种方式是使用 Vue 的内置指令:v-cloak,并且在 CSS 中设置样式。
[v-cloak] { display: none; }
答:使用 @click.native 来进行调用原生的 JS 事件。原因:router-link 会阻止 click 事件,.native 指直接监听一个原生事件。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online