1、什么是组件化、有什么好处、vue如何创建组件、vue组件之间如何通信
什么是组件化。
任何一个页面我们都可以抽象成一堆组件构成的一个大的组件树。
大到一个页面,小到一个按钮都可以是一个组件,一个页面就是由很多组件嵌套拼接组成,这就是组件化。
组件化的好处:复用性强、分公开发、代码好管理、耦合度低
vue如何创建组件 1、全局组件 2、局部组件 3、单文件组件
组件之间的通讯方式
Vue 组件间通信主要指以下
3 类通信:父子组件通信、隔代组件通信、兄弟组件通信,
下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。
(1)props / $emits
适用 父子组件通信
(2)ref
与 $parent / $children
适用 父子组件通信
ref
:
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;
如果用在子组件上,引用就指向组件实例
$parent / $children
:访问父 / 子实例
(3)EventBus ($emit / $on)
适用于 父子、隔代、兄弟组件通信
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
数据的发送:EventBus.$emit('接口', 数据)
数据的接收:EventBus.$on('接口', function(v){ // v发过来的数据 })
bus.js文件
import Vue from 'vue';
export default new Vue();
vue文件
import EventBus from 'common/js/bus.js';
methods: {
addCart(event) {
EventBus.$emit('getTarget', event.target);
}
}
(4)$attrs/$listeners
适用于 隔代组件通信
$attrs
:包含了父作用域中不被prop
所识别 (且获取) 的特性绑定 (class
和style
除外 )。当一个组件没有声明任何prop
时,这里会包含所有父作用域的绑定 (class 和 style
除外 ),并且可以通过v-bind="$attrs"
传入内部组件。通常配合inheritAttrs
选项一起使用。
$listeners
:包含了父作用域中的 (不含.native
修饰器的)v-on
事件监听器。它可以通过v-on="$listeners"
传入内部组件
(5)provide / inject
适用于 隔代组件通信
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
(6)Vuex 适用于 父子、隔代、兄弟组件通信
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
(7) 插槽 slot
(8)v-model
父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit('input',val)自动修改v-model绑定值
2、介绍一个vue,你觉得vue有什么特点,有什么好处,和其他你使用的框架有什么区别
vue是渐进式的JavaScript框架
既可以把vue当做第三方库来使用,也可以利用vue的构建复杂的单页项目
特点:入门容易,只需会html、css、js就可以,如果是react还要先学习ES6、jsx、函数式编程
高效:虚拟DOM
使用方便:指令、模板、数据双向绑定 和react相比,数据双向绑定可以自动修改,react需要手动执行setState
组件化,更容易被新手接收html css js 而react都是通过js实现
vue如何配置代理
新建vue.config.js文件
module.exports = {
devServe: {
proxy: '<url>'
changeOrigin: true
}
}
3、路由的原理是什么,如何实现
什么是路由
就是通过点击不同的按钮展示不同的页面或者组件的功能
路由原理
根据不同的路径地址,展示不同的页面、组件
路由实现
hash
#a
#b
history
/a
/b
如何监视这两者发生变化
hash
haschange
history
propstate
window.addEventListener('haschange', function(){},false)
window.addEventListener('propstate', function(){})
hash特点:
(1)hash虽然在URL中,但不被包括在HTTP请求中;
(2)用来指导浏览器动作,hash不会重加载页面。
4、说说你对 SPA 单页面的理解,它的优缺点分别是什么?
SPA(single page application)单页应用 仅在 web页面初始化时加载HTML,JavaScript,CSS,一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转,取而代之的是利用路由机制实现HTML内容的变换,必变页面的重新加载
优点:
1、用户体验好,快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
2、SPA 相对对服务器压力小;
3、前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
1、初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
2、前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
3、SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。
5、vue中v-if与v-show的区别以及使用场景
实现本质:
v-show
:通过display:none 和display:block之间切换
v-if
:通过Dom节点的插入、删除实现切换
性能对比:
v-if
:切换时需要删除、插入节点,开销大
但是在切换的初始化,如果条件是false是不会插入节点渲染的会节约性能
总结:如果不是频繁切换,渲染时条件渲染用v-if
v-show
:有更高的初始渲染开销,就算是false也会渲染
但是在切换的时候只是改变样式,消耗少
总结:在频繁切换的时候用v-show
区别
v-if是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当的被销毁和重建;
也是惰性的,如果再初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块
v-show不管初始条件是什么,元素总是会被渲染,并且只是简单的基于css的‘display’属性进行切换
v-if适用于运行时很少改变条件,不需要频繁切换条件的场景;v-show则适用于需要非常频繁的切换条件的场景。
6、method、computed、watch的区别
method 方法:
页面数据每次重新渲染都会重新执行,性能消耗大,除非不希望有缓存的时候用
computed
是计算属性,依赖其他属性计算值,并且computed的值有缓存,只有当计算值变化才有返回内容
watch
监听到值的变化就会执行回调,在毁掉中可以进行一些逻辑操作
总结:
- 除非不希望缓存,一般不会用method
- 一般来说需要依赖别的属性来动态获得值的时候可以用computed
- 对于监听到值的变化需要做异步操作或开销较大的操作时用watch
7、Class 与 Style 如何动态绑定?
class可以通过对象语法和数组语法进行动态绑定
对象语法:
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
data: {
isActive: true,
hasError: false
}
数组语法:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
style也可以通过对象语法和数组语法动态绑定:
对象语法:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
数组语法:
<div v-bind:style="[styleColor, styleSize]"></div>
data: {
styleColor: {
color: 'red'
},
styleSize:{
fontSize:'23px'
}
}
8、怎样理解 Vue 的单向数据流?
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:
父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
有两种常见的试图改变一个 prop 的情形 :
这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。
在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
这个 prop 以一种原始的值传入且需要进行转换。
在这种情况下,最好使用这个 prop 的值来定义一个计算属性
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
9、对MVVM的理解
MVVM分为 Model 、View、ViewModel三者
Model:代表数据模型,数据和业务逻辑都在Model层中定义;
View:代表UI视图,负责数据的展示;
ViewModel就是View与Model的连接器,View与Model通过ViewModel实现双向绑定。
10、什么是生命周期、vue的生命周期钩子函数有哪些、在工作中什么地方用过
什么是生命周期
生命周期就是物体从诞生到死亡的过程,vue的声明周期就是vue从初始化到销毁的过程
什么是钩子函数
在生命周期的过程中我们有很多特殊的时间段,我希望在这些特殊的时间段对vue做一些事情,所以出现了钩子函数
钩子函数就是作者在设计vue的时候,在vue从初始化到销毁这段时间内的特殊时间段给我们一些定义函数的权利
如果我们定义了就会执行,如果不定义就不会执行
vue都有哪些生命周期
beforeCreate 创建前
created 创建后
beforeMount 挂载前
mouted 挂载后
beforeUpdate 数据更新前
updated 数据更新后
beforeDestory 销毁前
destoryed 销毁后
** 这些有什么区别定义**
beforeCreate 创建前,刚执行new的操作,其他什么都没做
created 创建后,属性和方法挂载到了vue实例上
beforeMount 挂载前, 找到了el 或者mount对应的节点范围,但是数据还没替换
mouted 挂载后,vue范围内的变量都会被替换成data里面对应的数值
beforeUpdate 数据更新前
updated 数据更新后
beforeDestory 销毁前
destoryed 销毁后
11、Vue 的父组件和子组件生命周期钩子函数执行顺序?
Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:
- 加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
- 子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
- 父组件更新过程
父 beforeUpdate -> 父 updated
- 销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
12、keep-alive组件有什么作用
如果你需要在组件切换到时候,保存一些组件的状态防止多次渲染,就可以使用keep-alive组件包裹需要保存的组件
对于keep-alive组件来说,他拥有2个独有的 生命周期钩子函数,分别为 activated 和 deactivated
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:
一般结合路由和动态组件一起使用,用于缓存组件;
提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
13、组件中 data 为什么是一个函数?
为什么组件中的 data 必须是一个函数,然后 return 一个对象,而 new Vue 实例里,data 可以直接是一个对象?
组件复用时所有组件实例都会共享data,如果data是对象的话,就会造成一个组件修改data后,会影响到其他所有组件,所以需要将data写成函数,每次用到就调用一次函数获得新的数据
当我们用new Vue()的方式事,无论我们将data设置为对象还是函数都可以,因为new vue()的方式是生成一个根组件,该组件不会复用,也就不存在共享
如下:
data() {
return {
message: "子组件",
childName:this.name
}
}
// new Vue
new Vue({
el: '#app',
router,
template: '<App/>',
components: {App}
})
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。
14、什么是Vue Loader,为什么脚手架中style标签有scoped属性
Vue Loader就是把vue文件解析成浏览器能看懂的html、css、js文件
当然webpack中海油其他很多loader作用一样
scoped 属性表示他的css只作用于当前组件中的元素
15、v-model 的原理?
我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
以 input 表单元素为例:
<input v-model='something'>
相当于
<input v-bind:value="something" v-on:input="something = $event.target.value">
如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:
父组件:
<ModelChild v-model="message"></ModelChild>
子组件:
<div>{{value}}</div>
props:{
value: String
},
methods: {
test1(){
this.$emit('input', '小红')
},
},
16、vue中v-for中为什么要使用key
key的作用主要是为了高效的更新虚拟DOM。
17、vue中v-if和v-for为什么不能同时使用
同时使用会出现警告,原因是v-for的优先级优大于v-if
image.png
详细解释参考:https://www.cnblogs.com/showjs/p/11376446.html
18、forEach和for的区别
foreach适用于只是进行集合或数组遍历,for则在较复杂的循环中效率更高。
foreach不能对数组或集合进行修改(添加删除操作),如果想要修改就要用for循环。
所以相比较下来for循环更为灵活。
19、数组对象去重
const obj = [
{
id: 1,
name: 'Lily'
},
{
id: 2,
name: 'Lucy'
},
{
id: 3,
name: 'GaoFei'
},
{
id: 8,
name: 'Tom'
},
{
id: 1,
name: 'AiSa'
},
{
id: 9,
name: 'Jack'
}
]
var arr = []
var brr = []
obj.forEach((item, index) => {
if (!arr.includes(item.id)) {
arr.push(item.id)
brr.push(item)
}
})
console.log(brr)
console.log('------------------------------')
var newobj = {}
const pen = obj.reduce((cur, next) => {
newobj[next.id] ? '' : newobj[next.id] = true && cur.push(next)
return cur
}, [])
console.log(pen)
20、jquery同vue的区别
jquery是一个类库,vue是前端框架
转自:https://blog.csdn.net/tangxiujiang/article/details/79752131
21、this指向问题以及箭头函数的this指向问题 【()=>】
this指向谁在函数定义的时候无法确定,只有在函数调用的时候才能确定,谁调用就指向谁
箭头函数的this指向是固定的,固定在定义时所在的作用域
22、vue为什么要求组件模板只能有一个根元素?
太多根元素找不到入口
23、在.vue文件中style是必须的吗?那script是必须的吗?为什么?
template是必须的,而script与style都不是必须的。
24、vue-router 路由模式有几种?
3 种路由模式
- hash: 使用 URL hash 值来作路由。
- history : 依赖 HTML5 History API 和服务器配置。
- abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。
(1)hash 模式的实现原理
location.hash 的值就是 URL 中 # 后面的内容
例如https://www.word.com#search
的has值就是#search
- URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换; - 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
- 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
(2)history 模式的实现原理
HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:
window.history.pushState(null, null, path);
window.history.replaceState(null, null, path);
history 路由模式的实现主要基于存在下面几个特性:
- pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
- 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
- history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)
网友评论