1、Vue中的数据绑定
绑定数据有三种方式:
1】插值
也就是双大括号{{name}}的形式,以文本的形式和实例data中对应的属性进行绑定
2】v-bind
双大括号写法不能在 HTML 属性中使用,所以,v-bind用于v-bind动态给HTML的属性绑定指令
比如:v-bind:class、v-bind:id、v-bind:value、v-bind:style
3】v-model
v-model 用在表单控件类型的html标签上面的,用于实现双向数据绑定,所以如果你用在除了表单控件以外的标签是没有任何效果的。
比如input控件:、select 控件:
v-model 的本质是 v-bind:value + v-on:input的语法糖
2、v-model
v-model其实是个语法糖,它实际上是做了两步动作:
1】通过v-bind去绑定数据value(v-bind:value)
2】v-on:input 去触发输入事件input
等同于:
<input type=“text” v-bind:value=“username” @input=“username=$event.target.value” />
用 js 来实现v-model:
3、v-if与v-show的区别
相同点:v-if与v-show都可以动态控制dom元素显示隐藏
不同点:
v-if:动态增删dom元素,在切换过程中会有更多性能上的花销,相当于display:none;
v-show:动态显示隐藏dom元素,隐藏则是为该元素添加visibility:hidden,dom元素还在,具有较高的初始渲染消耗
如果需要频繁地切换,则使用v-show指令比较好,反之则使用v-if 比较好
4、v-on可以监听多个方法吗
可以
5、vue常见修饰符
a、表单修饰符
v-model.lazy:在我们输入完所有东西,光标离开才更新视图
v-model.trim:去除前后空格
v-model.number:
如果你先输入数字,那它就会限制你输入的只能是数字
如果你先输入字符串,那它就相当于没有加.number
b、事件修饰符
.stop:阻止事件冒泡
.prevent:用于阻止事件的默认行为,例如,当点击提交按钮时阻止对表单的提交。相当于调用了event.preventDefault()方法
.once:这个修饰符的用法也是和名字一样简单粗暴,只能用一次,绑定了事件以后只能触发一次,第二次就不会触发
c、v-bind修饰符
.sync:实现双向绑定
6、vue-cli构建的项目,如何升级vue的版本
npm install -g @vue/cli
7、vue事件中如何使用event对象
将一个特殊变量 $event 传入到回调中
8、v-for 与 v-if 的优先级
当v-for和v-if在同一个元素标签上时,v-for优先级高于v-if,也就是说在v-for的每次循环运行中都会调用v-if的判断,所以会出现问题,vue官网推荐将v-if移到父元素
9、Vue子组件调用父组件的方法
a、子组件中通过this.
e
m
i
t
或
者
t
h
i
s
.
emit 或者 this.
emit或者this.parent.event来调用父组件的方法(相反,父调子的话this.
c
h
i
l
d
r
e
n
或
者
t
h
i
s
.
children 或者 this.
children或者this.ref.xxx.fun())
父组件:
子组件:
b、在子组件里用$emit向父组件触发一个事件,父组件监听这个事件
父组件:
子组件:
10、vue中 keep-alive 组件的作用
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
比如:从列表页进入详情页,又返回列表页,要求页面不要重新刷新
一般配合vue-router和视图组件router-view一起使用
***特殊的钩子函数
activated:当keep-alive组件激活时将会调用
deactivated:当keep-alive组件停用时调用
注意:这两个钩子函数在服务器端渲染期间不被调用
11、vue更新数组时触发视图更新的方法
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
12、vue监听一些键盘事件
在我们的项目经常需要监听一些键盘事件来触发程序的执行,而Vue中允许在监听的时候添加关键修饰符:
13、vue watch深度监听
watch 里面还有一个属性 deep,默认值是 false,代表是否深度监听
可用于监听data里面对象属性的变化
14、如何解决非工程化项目,网速慢时初始化页面闪动问题?
当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码。
使用v-cloak指令,v-cloak不需要表达式,它会在Vue实例结束编译时从绑定的HTML元素上移除,经常和CSS的display:none配合使用。
这时虽然已经加了指令v-cloak,但其实并没有起到任何作用,当网速较慢、Vue.js 文件还没加载完时,在页面上会显示{{message}}的字样,直到Vue创建实例、编译模版时,DOM才会被替换,所以这个过程屏幕是有闪动的。只要加一句CSS就可以解决这个问题了:
[v-cloak]{
display:none;
}
在一般情况下,v-cloak是一个解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用。
15、什么是vue的计算属性?
通过计算属性,在模板{{xxx}}里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果;而且计算属性还可以依赖多个Vue 实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新。
16、Vue组件间的参数传递
1】父组件与子组件传值
父组件传给子组件:子组件通过props方法接受数据;
子组件传给父组件:$emit方法传递参数
2】非父子组件间的数据传递,兄弟组件传值
eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适。
3】vuex(见下)
17、vue中解决跨域问题
a、配置反向代理
config/index.js,在proxyTable中添写如下代码:
target 填入要代理的url
然后使用axios请求数据时直接使用“/api”
b、使用jsonp
可以使用vue-jsonp插件
18、vue如何禁止弹窗后面的滚动条滚动?
methods : {
//弹窗后,禁止滚动
stop(){
var mo=function(e){e.preventDefault();};
document.body.style.overflow=‘hidden’;
document.addEventListener(“touchmove”,mo,false);//禁止页面滑动
},
/弹窗关闭后,取消滑动限制/
move(){
var mo=function(e){e.preventDefault();};
document.body.style.overflow=‘’;//出现滚动条
document.removeEventListener(“touchmove”,mo,false);
}
}
19、vue-cli如何使用json数据模拟
mock数据写在json文件中,借助内置微型nodejs服务器dev server,然后把proxyTable 里将接口代理到具体mock数据json文件上
20、vue移动端h5页面根据屏幕适配的四种方案
1】引入淘宝开源的可伸缩布局方案lib-flexible
它主要是根据设备设备像素比设置scale的值,保持视口device-width始终等于设备物理像素,屏幕大小动态计算根字体大小,具体是将屏幕划分为10等分
2】viewport 的使用
3】使用rem,根据css的媒体查询动态设置根部html字体大小
21、vue中央事件总线的使用
通过 o n 和 on和 on和emit监听和发送消息
22、ajax、axios之间的详细区别以及优缺点
1】ajax
本身是针对MVC的编程,不符合现在前端MVVM的浪潮
基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案
JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)
2】axios
优点:
从 node.js 创建 http 请求
支持 Promise API
客户端支持防止CSRF
提供了一些并发请求的接口(重要,方便了很多的操作)
缺点:
一些默认的配置比如请求头的content-type,会引发跨域的问题
23、Vue相关的UI框架的源码阅读
storybook
24、provide 和 inject
1】作用
用于父组件向子孙组件传递数据
2】成对出现
provide和inject是成对出现的
3】使用方法
provide在父组件中返回要传给下级的数据,inject在需要使用这个数据的子辈组件或者孙辈等下级组件中注入数据
4】使用场景
由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject可以轻松实现跨级访问父组件的数据
5】注意
provide 和 inject 主要在开发高阶插件/组建库时使用,并不推荐用于普通应用程序代码中
25、全局定义过滤器
Vue.filter(‘capitalize’, function (value) {
if (!value) return ‘’
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
26、对keep-alive 的了解?
keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
比如:从列表跳到详情页,然后返回详情页的时候需要缓存列表页的状态(比如滚动位置信息),这个时候就需要保存状态,要缓存状态;vue里提供了keep-alive组件用来缓存状态
1】利用meta标签
在路由中的meta标签中记录keepAlive的属性为true,在需要缓存的router-view组件上包裹keep-alive组件:
由于有些情况下需要缓存有些情况下不需要缓存,可以在缓存的组件里的路由钩子函数中做判断:
beforeRouteLeave (to, from, next) {
this.loading = true
if (to.path === ‘/goods_detail’) {
from.meta.keepAlive = true
} else {
from.meta.keepAlive = false
// this.$destroy()
}
next()
},
2】使用include、exclude属性
是在vue2.0以后新增的属性
include是需要缓存的组件;
exclude是除了某些组件都缓存;
****注意:
因为组件被缓存了,再次进入缓存路由/组件时,不会触发这些钩子:// beforeCreate created beforeMount mounted 都不会触发
activated:在组件第一次渲染时会被调用,之后在每次缓存组件被激活时调用。
deactivated:组件被停用(离开路由)时调用
27、为什么 v-for 和 v-if 不建议⽤在⼀起?
首先v-for 优先级比v-if 高
不要把 v-if 和 v-for 同时用在同一个元素上,因为这样会带来性能方面的浪费(每次渲染都会先循环再进行条件判断)。如果避免出现这种情况,则在外层嵌套template(页面渲染不生成dom节点),在这一层进行v-if判断,然后在内部进行v-for循环。
vue-router相关知识点
1、想对路由参数的变化作出响应
a、watch (监测变化) $route
b、beforeRouteUpdate
注意:从同一个组件跳转到同一个组件,生命周期钩子created和mounted都不会调用
2、完整的 vue-router 导航解析流程
- 导航被触发
- 在失活的组件里调用离开守卫
- 调用全局的 beforeEach 守卫
- 在重用的组件里调用 beforeRouteUpdate 守卫
- 在路由配置里调用 beforEnter
- 解析异步路由组件
- 在被激活的组件里调用 beforeRouteEnter
- 调用全局的 beforeResolve 守卫
- 导航被确认
- 调用全局的 afterEach 钩子
- 触发 DOM 更新
- 在创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数
3、vue-router有哪几种导航钩子( 导航守卫 )?
vue-router 的导航钩子( 导航守卫 ),主要用来作用是拦截导航,让他完成跳转或取消
有三种方式可以植入路由导航过程中:
a、全局导航钩子
全局导航钩子对所有的路由都生效,主要有两种钩子:前置守卫、后置钩子
注册一个全局前置守卫:
to: Route,代表要进入的目标,它是一个路由对象
from: Route,代表当前正要离开的路由,同样也是一个路由对象
next: Function,这是一个必须需要调用的方法,而具体的执行效果则依赖 next 方法调用的参数
next():进入管道中的下一个钩子,如果全部的钩子执行完了,则导航的状态就是 confirmed(确认的):next(false):这代表中断掉当前的导航,即 to 代表的路由对象不会进入,被中断,此时该表 URL 地址会被重置到 from 路由对应的地址;next(‘/’) 和 next({path: ‘/’}):在中断掉当前导航的同时,跳转到一个不同的地址;next(error):如果传入参数是一个 Error 实例,那么导航被终止的同时会将错误传递给 router.onError() 注册过的回调
全局后置钩子:
不同于前置守卫,后置钩子并没有 next 函数,也不会改变导航本身
b、单个路由独享的
即单个路由独享的导航钩子,它是在路由配置上直接进行定义的
c、组件级的
组件内的导航钩子主要有这三种:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。他们是直接在路由组件内部直接进行定义的
需要注意是:
beforeRouteEnter 不能获取组件实例 this,因为当守卫执行前,组件实例被没有被创建出来,剩下两个钩子则可以正常获取组件实例 this
但是并不意味着在 beforeRouteEnter 中无法访问组件实例,我们可以通过给 next 传入一个回调来访问组件实例。在导航被确认是,会执行这个回调,这时就可以访问组件实例了,如:
注意,仅仅是 beforRouteEnter 支持给 next 传递回调,其他两个并不支持。因为归根结底,支持回调是为了解决 this 问题,而其他两个钩子的 this 可以正确访问到组件实例,所有没有必要使用回调
4、vue-router的几种实例方法以及参数传递
a、编程式的导航 router.push
注意:和name配对的是params,和path配对的是query
this.
r
o
u
t
e
r
.
p
u
s
h
(
p
a
t
h
:
′
/
n
e
w
s
′
,
q
u
e
r
y
:
u
s
e
r
I
d
:
123
)
t
h
i
s
.
router.push({ path: '/news', query: { userId: 123 }}) this.
router.push(path:′/news′,query:userId:123)this.router.push({ name: ‘news’, params: { userId: 123 }})
b、声明式的导航
声明式的导航和编程式的一样
click to news page
5、组件及其属性
组件支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。
比起写死的 会好一些,理由如下:
无论是 HTML5 history 模式还是 hash 模式,它的表现行为一致,所以,当你要切换路由模式,或者在 IE9 降级使用 hash 模式,无须作任何变动。
在 HTML5 history 模式下,router-link 会拦截点击事件,让浏览器不在重新加载页面。
当你在 HTML5 history 模式下使用 base 选项之后,所有的 to 属性都不需要写(基路径)了。
6、vue-router实现路由懒加载( 动态加载路由 )
像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时
使用import:
按需加载只需要修改vue文件的引入方式:
const RankList = () => import( /* webpackChunkName: “RankList” / ‘@/components/RankList’)
/ webpackChunkName: “RankList” */ 是打包后文件名称,后面是文件路径。
‘@/components/RankList’ 是文件路径。
7、两种路由模式
1】hash模式
本质:window.location.hash,用来获取或设置页面的标签值。
a. HTTP请求不包括#,#是用来指导浏览器动作的,对服务器端完全无用,对浏览器而言,就是一个位置标识符
b.单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页
c.每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录
2】history模式
利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如:http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误
注意:pushState和replaceState,都不会刷新浏览器页面。
8、router-link和传统a链接的区别
1】通过a标签进行跳转,页面会被重新渲染,即相当于重新打开一个新的网页,体现为视觉上的“闪烁”(如果是本地的项目基本看不出来)
2】通过router-link进行跳转不会跳转到新的页面,也不会重新渲染,它会选择路由所指的组件进行渲染,避免了重复渲染的“无用功”。
9、vue路由跳转的两种方法
和 this.$router.push(…)