看看面试题,只是为了查漏补缺,看看自己那些方面还不懂。切记不要以为背了面试题,就万事大吉了,最好是理解背后的原理,这样面试的时候才能侃侃而谈。不然,稍微有水平的面试官一看就能看出,是否有真才实学还是刚好背中了这道面试题。
(都是一些基础的vue面试题,大神不用浪费时间往下看)
一、对于MVVM的理解?
MVVM 是 Model-View-ViewModel 的缩写。
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View代表ui组件,也就是视图层,它负责将数据模型转化成ui展现出来。
ViewModel就监听模型数据的改变和控制视图行为,处理用户交互,简单理解就是一个同步ViewModel的对象,是连接ModelView的桥梁。ViewModel之间并没有直接联系,而是通过ViewModel进行交互,ModelViewModel 之间的交互式双向的 ,因此View数据的变化会同步到Model中,而Model数据的变化也会立即反应到View上。
ViewModel通过双向数据绑定把View层和Model层连接了起来,而ViewModel之间的同步工作完全是自动的,无需人为干涉,因此开发者只需要关注逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由MVVM来统一管理。
二、Vue的生命周期
beforeCreate(创建前) 实例在内存中被创建出来,还没有初始化好data和methods属性。
created (创建后):实例已经在内存中创建,已经初始化好data和method,此时还没有开始编译模板。
beforeMount (载入前)在挂载开始之前被调用。相关的render函数首次被调用。已经完成了编译模板,把data里面的数据和模板生产html。但是此时还没有挂载html到页面上。
mounted (载入后)挂载完成之后调用,完成模板中的html渲染到html页面中,此过程中进行ajax交互。
beforeUpdate (更新前) 状态更新之前执行函数,此时data中的状态值是最新的,但是界面上显示的数据还是旧的,因为还没有开始重新渲染DOM节点。
updated (更新后)此时data中的状态值和界面上显示的数据都已经完成了跟新,界面已经被重新渲染好了!
beforeDestory (销毁前) 在实例销毁之前调用。实例仍完全可用。
destroyed (销毁后)实例销毁后调用,Vue实例指示的所有东西都会解绑,所有的事件监听器都会被移除,所有的子实例也都会被销毁。组件已经被完全销毁,此时组建中所有data、methods、以及过滤器,指令等,都已经不可用了
1.什么是vue生命周期?
Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
2.vue生命周期的作用是什么?
它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
3.vue生命周期总共有几个阶段?
它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。
4.第一次页面加载会触发哪几个钩子?
beforeCreate, created, beforeMount, mounted 。
5.DOM 渲染在 哪个周期中就已经完成?
DOM 渲染在 mounted 中就已经完成了。
三、 Vue实现数据双向绑定的原理:
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
js实现简单的双向绑定

<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 = newValuedocument.getElementById('show').innerHTML = newValue}})document.addEventListener('keyup', function (e) {obj.txt = e.target.value})
</script>

1.父组件与子组件传值
父组件传给子组件:子组件通过props方法接受数据;
子组件传给父组件:$emit方法传递参数
2.非父子组件间的数据传递,兄弟组件传值
eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适。(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。技术只是手段,目的达到才是王道。)
五、Vue的路由实现:hash模式 和 history模式
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 依赖的页面。”
六、Vue与Angular以及React的区别?
(版本在不断更新,以下的区别有可能不是很正确。我工作中只用到vue,对angular和react不怎么熟)
1.与AngularJS的区别
相同点:
都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。

不同点:
AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。

2.与React的区别
相同点:
React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。
不同点:
React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。
七、vue路由的钩子函数
总体来讲vue里面提供了三大类钩子
1、全局钩子
2、某个路由独享的钩子
3、组件内钩子
三种路由钩子中都涉及到了三个参数,
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next(‘/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
(一).全局守卫(全局路由钩子)

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

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

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

to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数
注意:使用全局路由钩子, 一定要调用next()!!!
(二).路由独享的守卫(路由内钩子)
你可以在路由配置上直接定义 beforeEnter 守卫:

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

(三). 组件内的守卫(组件内钩子)
beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave

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

二. 路由钩子在实际开发中的应用场景
1.beforeEach的使用
使用场景: 一般用在跳转前需要做校验的地方,如:进入首页前做登录校验,如果已登录则跳转首页,否则跳转登录页。

//路由跳转前做判断
router.beforeEach((to, from, next) => {let hasLogin = Cookies.get('hasLogin'); //从cookies中获取是否已登陆过的信息if(hasLogin){next()}else{if(to.path == '/login'){next()}else{next({replace:true,name:'login',})}}
})

2 beforeRouteLeave的使用
(一) 清除当前组件中的定时器
当一个组件中有一个定时器时, 在路由进行切换的时候, 可使用beforeRouteLeave将定时器进行清楚, 以免占用内存:

beforeRouteLeave (to, from, next) {window.clearInterval(this.timer) //清楚定时器next()
}

(二) 当页面中有未关闭的窗口, 或未保存的内容时, 阻止页面跳转
如果页面内有重要的信息需要用户保存后才能进行跳转, 或者有弹出框的情况. 应该阻止用户跳转

beforeRouteLeave (to, from, next) {//判断是否弹出框的状态和保存信息与否if (this.dialogVisibility === true) {this.dialogVisibility = false //关闭弹出框next(false) //回到当前页面, 阻止页面跳转}else if(this.saveMessage === false) {alert('请保存信息后退出!') //弹出警告next(false) //回到当前页面, 阻止页面跳转}else {next() //否则允许跳转}
}

(三) 保存相关内容到本地或vuex中
当用户需要关闭页面时, 可以将公用的信息保存到本地或Vuex中

beforeRouteLeave (to, from, next) {localStorage.setItem(name, content); //保存到localStorage中next()
}

八、vuex是什么?怎么使用?哪种功能场景使用它?
Vuex是vue框架中状态管理。

应用场景有:单页应用中,组件之间的数据状态。
应用实例:
1、购物车功能;
2、下单页面有选择优惠券按钮,点击进入优惠券页面,选择后返回到下单页,数据会绑定回来,显示已选择的优惠券;
3、登录状态等等
工作流程:
1、数据从state中渲染到页面;

2、在页面通过dispatch来触发action;

3、action通过调用commit,来触发mutation;

4、mutation来更改数据,数据变更之后会触发dep对象的notify,通知所有Watcher对象去修改对应视图(vue的双向数据绑定原理)。
五大核心:
State
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
getters
类似vue的计算属性,主要用来过滤一些数据。

用法 vuex中:

 getters: {filteredList: state => {return state.list.filter(item => item > 5)}}

组件中:

 computed: {list() {return this.$store.getters.filteredList;}}

mutation
提交更改数据的方法,同步!必须是同步函数
使用vuex修改state时,有两种方式:
1)可以直接使用 this.store.state.变量=xxx;2)this.store.state.变量 = xxx; 2)this.store.state.变量=xxx;2)this.store.dispatch(actionType, payload)或者 this.$store.commit(commitType, payload)
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}
})store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

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

var app = new Vue({el: '#app',data: {    },// 创建指令(可以多个)directives: {// 指令名称dir1: {inserted(el) {// 指令中第一个参数是当前使用指令的DOMconsole.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>

十、vue如何自定义一个过滤器?

使用:
<div id="app"><input type="text" v-model="msg" />{{msg| capitalize }}
</div>js代码: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)
})

十一、对keep-alive 的了解?
keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。
使用方法:

<keep-alive include='include_components' exclude='exclude_components'><component><!-- 该组件是否缓存取决于include和exclude属性 --></component>
</keep-alive>

参数解释
include - 字符串或正则表达式,只有名称匹配的组件会被缓存
exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存
include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用v-bind 。
使用示例:

<!-- 逗号分隔字符串,只有组件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>

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

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

十四:什么是vue的计算属性?
答:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。
十五:vue等单页面应用及其优缺点
优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。
十六: Vue中常用的事件修饰符
v-on指令常用修饰符:
.stop:- 调用event.stopPropagation(),禁止事件冒泡。
.prevent:- 调用event.preventDefault(),阻止事件默认行为。
.capture:- 添加事件侦听器时使用 capture 模式。
.self:- 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias}: - 只当事件是从特定键触发时才触发回调。
.native:- 监听组件根元素的原生事件。
.once:- 只触发一次函调。
.left:- (2.2.0) 只当点击鼠标左键时触发。
.right:- (2.2.0)只当点击鼠标右键时触发。
.Middle:- (2.2.0)只当点击鼠标中键时触发。
.passive:- (2.3.0)以 { passive:true } 模式添加侦听器。
注意:如果是在自己封装的组件或者是使用一些第三方的UI库时,会发现并不起效果,这时就需要 .native 修饰符了,如:

<el-input v-model="inputName" placeholder="搜索你的文件" @keyup.enter.native="searchFile(parmes)">
</el>

v-bind 指令常用修饰符:
.prop:- 被用于绑定 DOM 属性 (property)。
.camel:- (2.0.1+)将kebab-case 特性名转换为 camelCase。(从2.1.0开始支持)
.sync:- (2.3.0+)语法糖,会拓展成一个更新父组件绑定值的 v-on 侦听器。
v-model 指令常用修饰符:
.lazy:- 取代 input 监听 change 事件。
.number:- 输入字符串转为数字。
.trim:- 输入首尾空格过滤。
十七:谈谈你对axios的理解
1、axios的特点
一、Axios 是一个基于 promise 的 HTTP 库,支持promise所有的API
二、它可以拦截请求和响应
三、它可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
四、安全性更高,客户端支持防御 XSRF
2、axios的常用方法:
一、axios.get(url[, config]) //get请求用于列表和信息查询
二、axios.delete(url[, config]) //删除
三、axios.post(url[, data[, config]]) //post请求用于信息的添加
四、axios.put(url[, data[, config]]) //更新操作
五、 axios…patch只对更改过的数据进行更新
3、axios相关配置属性
url是用于请求的服务器URL

method是创建请求时使用的方法,默认是get

baseURL将自动加在url前面,除非url是一个绝对URL。它可以通过设置一个baseURL便于为axios实例的方法传递相对URL

transformRequest允许在向服务器发送前,修改请求数据,只能用在’PUT’,'POST’和’PATCH’这几个请求方法

headers是即将被发送的自定义请求头

headers:{'X-Requested-With':'XMLHttpRequest'},

params是即将与请求一起发送的URL参数,必须是一个无格式对象(plainobject)或URLSearchParams对象

params:{ID:12345
},

auth表示应该使用HTTP基础验证,并提供凭据
这将设置一个Authorization头,覆写掉现有的任意使用headers设置的自定义Authorization

auth:{username:'janedoe',
password:'s00pers3cret'
},

'proxy’定义代理服务器的主机名称和端口
auth表示HTTP基础验证应当用于连接代理,并提供凭据
这将会设置一个Proxy-Authorization头,覆写掉已有的通过使用header设置的自定义Proxy-Authorization头。

proxy:{host:'127.0.0.1',
port:9000,
auth::{username:'mikeymike',
password:'rapunz3l'
}
},

十八:vue组件中的data为什么必须是函数?
Object是引用数据类型,如果不用function 返回,每个组件的data 都是内存的同一个地址,一个数据改变了其他也改变了;

javascipt只有函数构成作用域(注意理解作用域,只有函数的{}构成作用域,对象的{}以及 if(){}都不构成作用域),data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响

举个例子:

const MyComponent = function() {};
MyComponent.prototype.data = {a: 1,b: 2,
}
const component1 = new MyComponent();
const component2 = new MyComponent();component1.data.a === component2.data.a; // true;
component1.data.b = 5;
component2.data.b // 5

如果两个实例同时引用一个对象,那么当你修改其中一个属性的时候,另外一个实例也会跟着改;
两个实例应该有自己各自的域才对,需要通过下面的方法来进行处理

const MyComponent = function() {this.data = this.data();
};
MyComponent.prototype.data = function() {return {a: 1,b: 2,}
};

这样么一个实例的data属性都是独立的,不会相互影响了.
所以,你现在知道为什么vue组件的data必须是函数了吧。这都是因为js本身的特性带来的,跟vue本身设计无关。其实vue不应该把这个方法名取为data(),应该叫setData或其他更容易理解的方法名。

十九:vue中解决跨域问题
方法1.后台更改header

header('Access-Control-Allow-Origin:*');//允许所有来源访问
header('Access-Control-Allow-Method:POST,GET');//允许访问的方式   

方法2.使用JQuery提供的jsonp
复制代码
methods: {
getData () {
var self = this
$.ajax({
url: ‘http://f.apiplus.cn/bj11x5.json’,
type: ‘GET’,
dataType: ‘JSONP’,
success: function (res) {
self.data = res.data.slice(0, 3)
self.opencode = res.data[0].opencode.split(’,’)
}
})
}
}

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

例如请求的url:“http://f.apiplus.cn/bj11x5.json”

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

proxyTable: { '/api': {  //使用"/api"来代替"http://f.apiplus.c" target: 'http://f.apiplus.cn', //源地址 changeOrigin: true, //改变源 pathRewrite: { '^/api': 'http://f.apiplus.cn' //路径重写 } }
}

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

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

通过这中方法去解决跨域,打包部署时还按这种方法会出问题。解决方法如下:
在config目录下dev.env.js中配置开发路径:

module.exports = merge(prodEnv, {NODE_ENV: '"development"',API_HOST: '"/api"' // 配置代理路径的符号,增加的内容})

在config目录下prod.env.js中配置开发路径:

module.exports = {NODE_ENV: '"production"',API_HOST: '"http://139.xxx.xx"' // 生产环境地址,增加的内容}

在vue2.x中 只需要在config文件里做修改即可

但是 在3.x中由于轻量级 导致config 文件不存在了。

所以要改开发环境时需要在根目录下新建一个文件
比如 .env.gray
在这个文件里面写

NODE_ENV = 'gray' //这里写的是等下在package.json下增加的运行变量
VUE_APP_URL = 'http://xxxxx' //这里写请求的网址

最后在package.json中
增加一个属性


然后在运行npm run gray打包 访问本地路径时就可以了

二十:computed 和 watch 的区别和运用的场景?
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
二十一:插槽的用法
在一个组件中使用 标签,就是定义一个插槽。在使用这个组件的时候允许在组件标签中添加内容包括添加组件 htmL 等任何模板代码
它允许你像这样合成组件:

<navigation-link url="/profile">Your Profile
</navigation-link>

然后你在 的模板中可能会写为:

<av-bind:href="url"class="nav-link"
><slot></slot>
</a>

当组件渲染的时候, 将会被替换为“Your Profile”。插槽内可以包含任何模板代码,包括 HTML:

<navigation-link url="/profile"><!-- 添加一个 Font Awesome 图标 --><span class="fa fa-user"></span>Your Profile
</navigation-link>

甚至其它的组件:

<navigation-link url="/profile"><!-- 添加一个图标的组件 --><font-awesome-icon name="user"></font-awesome-icon>Your Profile
</navigation-link>

如果 没有包含一个 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
编译作用域
当你想在一个插槽中使用数据时,例如:

<navigation-link url="/profile">Logged in as {{ user.name }}
</navigation-link>

该插槽跟模板的其它地方一样可以访问相同的实例属性 (也就是相同的“作用域”),而不能访问 的作用域。例如 url 是访问不到的:

<navigation-link url="/profile">Clicking here will send you to: {{ url }}<!--这里的 `url` 会是 undefined,因为 "/profile" 是_传递给_ <navigation-link> 的而不是在 <navigation-link> 组件*内部*定义的。-->
</navigation-link>

作为一条规则,请记住:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
具名插槽
有时我们需要多个插槽。例如对于一个带有如下模板的 组件:

<div class="container"><header><!-- 我们希望把页头放这里 --></header><main><!-- 我们希望把主要内容放这里 --></main><footer><!-- 我们希望把页脚放这里 --></footer>
</div>

对于这样的情况, 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

<div class="container"><header><slot name="header"></slot></header><main><slot></slot></main><footer><slot name="footer"></slot></footer>
</div>

一个不带 name 的 出口会带有隐含的名字“default”。

在向具名插槽提供内容的时候,我们可以在一个 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

<base-layout><template v-slot:header><h1>Here might be a page title</h1></template><p>A paragraph for the main content.</p><p>And another one.</p><template v-slot:footer><p>Here's some contact info</p></template>
</base-layout>

现在 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 中的内容都会被视为默认插槽的内容。

然而,如果你希望更明确一些,仍然可以在一个 中包裹默认插槽的内容:

<base-layout><template v-slot:header><h1>Here might be a page title</h1></template><template v-slot:default><p>A paragraph for the main content.</p><p>And another one.</p></template><template v-slot:footer><p>Here's some contact info</p></template>
</base-layout>

任何一种写法都会渲染出:

<div class="container"><header><h1>Here might be a page title</h1></header><main><p>A paragraph for the main content.</p><p>And another one.</p></main><footer><p>Here's some contact info</p></footer>
</div>

注意 v-slot 只能添加在 上 (只有一种例外情况),这一点和已经废弃的 slot 特性不同。
作用域插槽
先看一个最简单的例子!!
我们给元素上定义一个属性say(随便定义的!),接下来在使用组件child,然后在template元素上添加属性slot-scope!!随便起个名字a

我们把a打印一下发现是 {“say” : “你好”},也就是slot上面的属性和值组成的键值对!!!
这就是作用域插槽!
我可以把组件上的属性/值,在组件元素上使用!!

<div id="app"><child><template slot-scope="a"><!-- {"say":"你好"} -->{{a}}</template></child>
</div>
<script>Vue.component('child',{template:`<div><slot say="你好"></slot></div>`})let vm = new Vue({el:'#app',data:{}})
</script>

再看一下下面的例子:

<div id="app"><child :lists="nameList"><template slot-scope="a">{{a}}</template></child>
</div>
<script>Vue.component('child',{props:['lists'],template:`<div><ul><li v-for="list in lists"><slot :bbbbb="list"></slot></li></ul></div>`})let vm = new Vue({el:'#app',data:{nameList:[{id:1,name:'孙悟空'},{id:2,name:'猪八戒'},{id:3,name:'沙和尚'},{id:4,name:'唐僧'},{id:5,name:'小白龙'},]}})
</script>

看一下输出结果

这样我就可以在这元素上随便玩了啊!!
当id等于1的时候,我前面加个你好。
我可以随便根据这个对象的属性值进行操作!

<child :lists="nameList"><template slot-scope="a"><div v-if='a.bbbbb.id==1'>你好:<span>{{a.bbbbb.name}}</span></div><div v-else>{{a.bbbbb.name}}</div></template></child>

最后!如果用过elementui的同学,一定知道表格就是这样来的!!
表格的本质就是这样!

如果你的才华还实现不了你的野心,那就静下心来,埋头苦干。有志者事竟成破釜成舟百二秦关终属楚,苦心人天不负卧薪尝胆三千越甲可吞吴!

Vue 中常见的面试题/知识点整理相关推荐

  1. 2021年Vue最常见的面试题以及答案(面试必过)

    Vue常见面试题 Vue的优点 说说你对SPA单页面的理解,它的优缺点分别是什么? SPA首屏加载速度慢的怎么解决? Vue初始化过程中(new Vue(options))都做了什么? 对MVVM的理 ...

  2. kafka面试题知识点整理

    kafka-面试题整理 刚刚学了kafka,整理一些面试题知识点,帮助记忆 1.什么是kafka 2.什么是消息队列 3.kafka通信流程 4.Leader选举流程 5.副本及同步原理 6.消费者消 ...

  3. 2022年Vue最常见的面试题以及答案(面试必过)

    Vue 的优点 说说你对 SPA 单页面的理解,它的优缺点分别是什么? SPA 首屏加载速度慢的怎么解决? Vue 初始化过程中(new Vue(options))都做了什么? 对MVVM的理解? V ...

  4. Vue最常见的面试题以及答案

    写在前面 CSDN话题挑战赛第1期 活动详情地址:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f 参赛话题:前端面试宝典 话 ...

  5. 常见SQL面试题知识点+使用技巧

    点击关注上方"数据不吹牛", 设为"置顶或星标",第一时间送达干货 SQL是用于数据分析和数据处理的最重要的编程语言之一,因此与数据科学相关的工作(例如数据分析 ...

  6. 那些git中常见的面试题及知识点

    1.列举工作中常用的git命令 1.新增文件的命令:git add file或者git add . 2.提交文件的命令:git commit –m或者git commit –a 3.查看工作区状况:g ...

  7. JAVA 150道笔试题知识点整理

    JAVA 笔试题 整理了几天才整理的题目,都是在笔试或者面试碰到的,好好理解消化下,对你会有帮助,祝你找工作顺利,收到满意的 offer . 1.Java 基础知识 1.1 Java SE 语法 &a ...

  8. C++面试题知识点整理

    近期在找工作,面的基本上是C/C++相关岗位,整理了一些网上提到的面试题或者知识点,慢慢补充吧,有错误的地方欢迎指出.  下面整理归纳了面试中常问到的题目,分为5大类:  - C++知识点;  - 操 ...

  9. datagrid如何获取一行数据中的某个字段值_SQL中常见的面试题

    大家在面试数据分析岗或其他岗位的时候,时常会被问到一些SQL题,我今天就将常被问到的一些SQL题及答案整理下,给大家做个参考! 案例所使用的表为: (一)各种连接函数的区别? (1)inner joi ...

最新文章

  1. QuartzCore框架-- iOS中的动画
  2. c语言结果用全局变量返回,c语言参数传递和返回值及变量存储.doc
  3. 常用的meta标签总结
  4. Mule ESB,ActiveMQ和DLQ
  5. Java讲课笔记02:Java集成开发环境
  6. 解决iSlider的一些问题(滑动组件)
  7. 【中级05】Java泛型、反射
  8. DevExpress ChartControl 绘制圆滑曲线
  9. win10开卓越性能模式方法
  10. java文件恢复软件,误删文件恢复-误删文件恢复大师 v1.1.0 最新版
  11. (57)Linux驱动开发之三Linux字符设备驱动
  12. python当前运行目录_Python获取运行目录与当前脚本目录的方法
  13. 再见!Notepad++
  14. 淘宝直播赚佣金项目玩法
  15. Day020 - pdf合并与excel/csv读取写入
  16. Python 绘制椭圆 平移 旋转
  17. 聊天室c语言程序,socket 多线程聊天室的实现(C语言)
  18. 48万奖金等你瓜分! 2019华为开发者大赛全栈开放!
  19. Qt工程生成MiniDump文件
  20. Android Q 强制黑暗模式(ForceDark) | 原理 实践

热门文章

  1. 【拓扑排序+dp】Hzy's Rabbit Candy
  2. apache带宽配置
  3. luhn算法 java_java – 使用luhn算法验证信用卡号
  4. html打开xls文件并显示其内容 demo
  5. 树莓派外接can模块,can收发功能测试
  6. (一看就会)让VM虚拟机之间联网并能相互ping通
  7. 关于Keil编译程序出现“File has been changed outside the editor,reload?”的解决方法
  8. MySQL单表膨胀优化之MyCat分库分表
  9. 木板切割最优matlab,矩形木板最优切割方案的设计与实现
  10. mysql使用结巴语句_结巴分词 java 高性能实现,是 huaban jieba 速度的 2倍