- 计算属性如何使用
Vue模板中的表达式很便利,但放入太多的逻辑会让html模板过重
难以维护;所以我们把复杂的逻辑处理放到计算属性里使用
我们可以像绑定普通属性一样绑定计算属性,因为计算属性依赖于data
中的数据,当数据发生改变时,计算属性也会更新。
- watch 如何使用
Watch用来监测vue实例上的数据变动,对应一个对象,键是观察表达式,值是对应回调。值也可以是方法名,或者是对象,包含选项。也可以直接调用this.$watch(‘’,回调函数)来进行数据监测
监测对象的时候需要添加一个选项deep:true
deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler。
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
immediate: true代表在wacth里声明了方法之后立即先去执行handler方法
- 计算属性和watch的区别
watch和computed都是以Vue的依赖追踪机制为基础,它们都试图处理这样一件事情:当某一个数据(称它为依赖数据)发生变化的时候,所有依赖这个数据的“相关”数据“自动”发生变化,也就是自动调用相关的函数去实现数据的变动。
watch是观察是一个动作; computed是一个计算的属性
watch能监听vue数据 compute本来就是响应的,且自动更新
Computed计算属性是一个值依赖了其他的值,依赖于他所使用的data中的属性,计算属性还有set和get方法
Watch监听的是你定义的变量,当你定义的变量发生变化的时候,调用对应的方法,也可以监测路由对象的变化,但是代码重复性很大,watch适用于当data发生变化时,执行异步操作或较大开销的时候;
- watch擅长处理的场景:一个数据影响多个数据
2. computed擅长处理的场景:一个数据受多个数据影响
watch是数据发生变化就会重新渲染,而computed不会重新计算,只有依赖的值有变化时,才会去重新计算,这就是computed的缓存
- prop 验证,和默认值
我们在父组件给子组件传值得时候,为了避免不必要的错误,可以给prop的值进行类型设定,让父组件给子组件传值得时候,更加准确,prop可以传一个数字,一个布尔值,一个数组,一个对象,以及一个对象的所有属性。
组件可以为 props 指定验证要求。如果未指定验证要求,Vue 会发出警告
比如传一个number类型的数据,用defalt设置它的默认值,如果验证失败的话就会发出警告。
- 插槽,具名插槽,插槽默认内容、
当我们定义了一个子组件,父组件在使用的这个组件的时候,想在内部自定义一些初始化数据,这时候就可以用slot实现,另一种 slot 特性的用法是直接用在一个普通的元素上
具名插槽----通过给子组件slot绑定一个name属性,然后在父组件设置slot属性,属性值对应子组件的name属性值
我们还是可以保留一个未命名插槽,这个插槽是默认插槽,也就是说它会作为所有未匹配到插槽的内容的统一出口
不设置name就是默认内
直接在solt里设置默认内容如果父组件为这个插槽提供了内容,则默认的内容会被替换掉。
- 作用域插槽 *
1、可以通过 slot-scope 特性从子组件获取数据
2、也就可以做到,把slot 中要渲染的,具体每一项,拿到父组件中单独处理渲染。
- 动态组件
在一个界面中使用 component v-bind:is 特性来切换不同的组件
- 动态组件上使用keep-alive(keep-alive的作用,组件如何优化)
动态切换组件,和路由跳转组件,都会重新创建组件的,但是有的时候我们更希望那些标签的组件实例能够缓存下来。这时候使用一个 <keep-alive> 元素将其组件包裹起来。提高性能,避免组件重绘。
9 子组件访问父组件实例子 $parent 父组件访问子组件变量 this.$refs.usernameInput
通过this.$props来访问父组件实例就可以
子传父
子组件访问父组件数据 通过在子组件使用this.$parent来访问
this.$refs.usernameInput
父组件访问子组件数据 给他添加ref属性,然后通过this.$refs.属性名.数据
10vue双向数据绑定原理 *
1、Vue 将遍历Vue 实例的 data 选项里的数据所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
2、在内部 getter/setter 让vue 追踪依赖,在属性被访问和修改时通知变化。
其变化可以需要安装 vue-devtools 来获取检查。
3、每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为监测项,之后当监测项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
11 vue 组件通信(父子,子父,兄弟, 深度嵌套)
父组件向子组件传值:
1)子组件在props中创建一个属性,用来接收父组件传过来的值;
2)在父组件中注册子组件;
3)在子组件标签中添加,子组件props中创建的属性;
4)把需要传给子组件的值赋给该属性
子组件向父组件传值:
1)子组件中需要以某种方式(如点击事件)的方法来触发一个自定义的事件;
2)将需要传的值作为$emit的第二个参数,该值将作为实参传给响应事件的方法;
3)在父组件中注册子组件并在子组件标签上绑定自定义事件的监听。
兄弟组件间通信
借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发
var bus = new Vue();
bus.$emit()
bus.$on()
熊大想要发消息给熊二,
接收方(熊二):事件绑定
bus.$on('customEvent',function(msg){
//msg就是通过事件 传递来的数据
})
发送方(熊大):触发事件
bus.$emit('customEvent',123);
12 vue 生命周期
BeforeCreate 实例创建之前调用
Created 实例创建成功,此时data中的数据已经初始化
beforeMount 挂载之前的状态,
Mounted 已经挂载的状态
BeforeUpdate 数据更新前的状态
Updated 数据更新完成时的状态
beforeDestory 在vue实例销毁之前调用,
Destoryed 在vue实例销毁之后调用,vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
13 vue webpack打包项目修改哪些配置 *
1.图片和背景图片出不来:
1、找到 config->index.js里面的build里的assetsPublicPath属性把他改为“./”
2、找到 build->utils.js,在里面加入一句publicPath:’../../’,
- 字体图标出不来
修改webpack.prod.conf.js把extract:true改为false
- 项目的登录拦截及用户权限访问控制问题。
对未登录的用户进行路由拦截和用户的权限访问,我们用vue脚手架搭建的都是纯前端的路由访问
Vue的项目路径里都有这个#号,这是一个锚点,说明我们的页面靠后端可能控制不了你的路由了,这时候你需要进行Vue的路由拦截。(Vue-router 有个模式可以改为history ,但是改成这个模式后需要后端的服务有对应的兼容,否则会造成某些页面刷新找不到页面,而且不会出现404页面,需要自己写路由去匹配404页面,慎用) 。这时候我们需要在router的里面添加meta字段进行自定义一些信息
meta:{requireAuth:true}
然后再main.js 加入全局的路由拦截。
router.beforeEach((to, from, next) =>{
if(to.meta.requireAuth){ //是否需要登录拦截
if(store.state.tokens.token){ //已登录
next()
}else{
next({
path: '/',
query: {redirect : to.fullPath}
})
}
}else{
next()
}
})
同理,用户权限的认证也可以这么做。另外需要注意的是,这个登录状态需要使用localstorage或者cookie保存,只存在store里面会导致页面一刷新登录状态就没了(当然你可以在页面mounted的时候去后台获取状态,然后改变store)。
- 部署的生产环境上后和开发环境的样式不一样
快上线了居然发现npm run build 之后放到服务器端竟然样式和开发环境的不一样,有点坑!
项目中使用了element-UI的组件,然后自己重写了部.盖了,但在本地却不会出现这个问题(这个不清楚为啥)解决办法:
<style>(不加scoped),在这里面改样式,或者在覆盖elementUI 样式的时候在class前面加上body 提高该样式优先级,就不会被覆盖了。另外自己的样式要写的规范,合乎正常的思维。这个也提醒我们,代码要提前放到服务端试一试。
- 代码格式、编辑器不统一造成代码格式混乱,注意优化代码
这个无关Vue,但是还是建议一个团队尽量统一代码编辑器,并且使用eslint进行代码格式检查,否则会造成代码在不同编辑器下显示混乱,很不容易队友阅读和修改,并且要时刻注意优化自己的代码,简化复杂的处理逻辑,否则会给日后的维护造成极大的困难
五.can't not find 'xxModule' - 找不到某些依赖或者模块
这种情况一般报错信息可以看到是哪个包抛出的信息.
一般卸载这个模块,安装重新安装下即可.
六.我用了 axios , 为什么 IE 浏览器不识别(IE9+)
那是因为 IE 整个家族都不支持 promise, 解决方案:
npm install es6-promise
// 在 main.js 引入即可// ES6的polyfillrequire("es6-promise").polyfill();
14 vue路由传参数
使用query方法传入的参数使用this.$route.query接受
使用params方式传入的参数使用this.$route.params接受
15 路由导航守卫 *
路由导航守卫分为3种,第一种是全局守卫:router.beforeEach
他有三个参数,to和from是将要进入和将要离开的路由对象,路由对象指的是平时通过this.$route获取到的路由对象。
next:Function 这个参数是个函数,且必须调用,否则不能进入路由(页面空白)。
next() 进入该路由。
next(false): 取消进入路由,url地址重置为from路由地址(也就是将要离开的路由地址)。
next 跳转新路由,当前的导航被中断,重新开始一个新的导航。
我们可以这样跳转:next('path地址')或者next({path:''})或者next({name:''})
且允许设置诸如 replace: true、name: 'home' 之类的选项
以及你用在router-link或router.push的对象选项。
第二种是:路由独享守卫
如果不想使用全局守卫的话,可以为某些路由单独配置守卫
参数用法什么的都一样,调用顺序在全局前置守卫后面,所以不会被全局守卫覆盖
- 第三种就是组件内的路由守卫:beforeRouteEnter 进入路由前
- beforeRouteUpdate (2.2) 路由复用同一个组件时
- beforeRouteLeave 离开当前路由时
beforeRouteEnter访问this
因为钩子在组件实例还没被创建的时候调用,所以不能获取组件实例 this,可以通过传一个回调给next来访问组件实例 。
但是回调的执行时机在mounted后面,所以在我看来这里对this的访问意义不太大,可以放在created或者mounted里面。
beforeRouteLeave:
导航离开该组件的对应路由时调用,我们用它来禁止用户离开,比如还未保存草稿,或者在用户离开前,将setInterval销毁,防止离开之后,定时器还在调用。
16 什么是vuex,使用vuex的好处
Vuex 是一个专门为 Vue.js 应该程序开发的状态管理模式
可以理解为是一个全局对象,所有页面都可以访问。
方便数据共享和传递等等。
做数据的共享、如果没有vuex、一个页面的数据想要到另一个页面、就不方便调用
比如用户做了一些加减的操作、三个页面都要用、可以用传参、但是很麻烦、这种时候用vuex就简单一些
不同组件之间共享状态,可以进行状态的修改和读取。
还有比较重要的单一状态树管理,让数据的修改脉络更加清晰,便于定位问题。
还有就是模块化module等
17 state,getter,mutation,action,module,plugins 各自的用途,和用法
state:储存初始化数据
Getters:对state里面的数据二次处理(对数据进行过滤类似filter的作用)比如state返回的为一个对象,如果想取对象中一个键的值用这个方法。
Mutation:对数据进行计算的方法全部写在里面(类似computed)在页面中触发时使用this.$stote.commit 触发mutations方法改变state的值。
Actions:处理mutations中已经写好的方法,直接触发方式是this.$store.dispatch(actionName)。
Module:
模块
Plugins:插件就是一个钩子函数,在初始化store的时候引入即可,
18 vuex中使用persistedstate 插件进行长久储存 (需要自己写代码测试) *
手动存取 localStorage 的方式还可以做得更简便。那就是引入 vuex-persist 插件,它就是为 Vuex 持久化存储而生的一个插件。不需要你手动存取 storage ,而是直接将状态保存至 cookie 或者 localStorage 中。
使用方法
安装:npm install --save vuex-persist
导入:import VuexPersistence from 'vuex-persist'
创建一个对象:
const vuexLocal = new VuexPersistence({
storage: window.localStorage
})
安装进vuex插件:
const store = new Vuex.Store<State>({
state: { ... },
mutations: { ... },
actions: { ... },
plugins: [vuexLocal.plugin]
})
通过以上设置,在图3中各个页面之间跳转,如果刷新某个视图,数据并不会丢失,依然存在,并且不需要在每个 mutations 中手动存取 storage 。
19 vue开发中遇到的问题
对未登录的用户进行路由拦截和用户的权限访问,我们用vue脚手架搭建的都是纯前端的路由访问
Vue的项目路径里都有这个#号,这是一个锚点,说明我们的页面靠后端可能控制不了你的路由了,这时候你需要进行Vue的路由拦截。(Vue-router 有个模式可以改为history ,但是改成这个模式后需要后端的服务有对应的兼容,否则会造成某些页面刷新找不到页面,而且不会出现404页面,需要自己写路由去匹配404页面,慎用) 。这时候我们需要在router的里面添加meta字段进行自定义一些信息
meta:{requireAuth:true}
然后再main.js 加入全局的路由拦截。
router.beforeEach((to, from, next) =>{
if(to.meta.requireAuth){ //是否需要登录拦截
if(store.state.tokens.token){ //已登录
next()
}else{
next({
path: '/',
query: {redirect : to.fullPath}
})
}
}else{
next()
}
})
同理,用户权限的认证也可以这么做。另外需要注意的是,这个登录状态需要使用localstorage或者cookie保存,只存在store里面会导致页面一刷新登录状态就没了(当然你可以在页面mounted的时候去后台获取状态,然后改变store)。
- 组件的异步加载(按需加载组件)
在平时的demo中,你可能不会遇见这个需求,当页面很多,组件很多的时候,你会发现你的页面在首次加载的时候,异常的慢,这个是因为vue首次加载的时候把可能一开始看不见的组件也一次加载了,这个时候就需要对页面优化了,就需要异步组件了。如何去写异步组件呢,实际上很简单,只需要在你的路由index,js里加上require就可以了,像下面这样,这也是所谓的按需加载组件的实现原理。
{
path: '/home',
name: 'Home',
component: function(resolve){
require(['@/views/home'], resolve)
}
}
- 部署的生产环境上后和开发环境的样式不一样
快上线了居然发现npm run build 之后放到服务器端竟然样式和开发环境的不一样,有点坑!
项目中使用了element-UI的组件,然后自己重写了部.盖了,但在本地却不会出现这个问题(这个不清楚为啥)解决办法:
<style>(不加scoped),在这里面改样式,或者在覆盖elementUI 样式的时候在class前面加上body 提高该样式优先级,就不会被覆盖了。另外自己的样式要写的规范,合乎正常的思维。这个也提醒我们,代码要提前放到服务端试一试。
- 代码格式、编辑器不统一造成代码格式混乱,注意优化代码
这个无关Vue,但是还是建议一个团队尽量统一代码编辑器,并且使用eslint进行代码格式检查,否则会造成代码在不同编辑器下显示混乱,很不容易队友阅读和修改,并且要时刻注意优化自己的代码,简化复杂的处理逻辑,否则会给日后的维护造成极大的困难
五.can't not find 'xxModule' - 找不到某些依赖或者模块
这种情况一般报错信息可以看到是哪个包抛出的信息.
一般卸载这个模块,安装重新安装下即可.
六.我用了 axios , 为什么 IE 浏览器不识别(IE9+)
那是因为 IE 整个家族都不支持 promise, 解决方案:
npm install es6-promise
// 在 main.js 引入即可// ES6的polyfillrequire("es6-promise").polyfill();
七.为什么我的引入的小图片渲染出来却是 data:image/png;base64xxxxxxxx
这个是 webpack 里面的对应插件处理的.
对于小于多少 K 以下的图片(规定的格式)直接转为 base64格式渲染;
具体配置在webpack.base.conf.js里面的 rules里面的 url-loader
这样做的好处:在网速不好的时候先于内容加载和减少http的请求次数来减少网站服务器的负担。
八、.路由变化页面数据不刷新问题
这种情况一般出现在vue-router的history模式下,初次进入会执行钩子函数,再次进入时则不会。
解决方案:用watch监听
watch : {
"$route" (to, from) {
if(to.path.indexOf('/home') > -1) {
this.initData()
}
}
}
- setInterval路由跳转继续运行并没有及时进行销毁
比如一些弹幕,走马灯文字,这类需要定时调用的,路由跳转之后,因为组件已经销毁了,但是setInterval还没有销毁,还在继续后台调用,控制台会不断报错,如果运算量大的话,无法及时清除,会导致严重的页面卡顿。
解决方案:在组件生命周期beforeDestroy停止setInterval
beforeDestory() {
clearInterval(this.timer);
MessageBox.close()
}
20 vue 组件按需加载
第一种:组件的异步加载(按需加载组件)
在平时的demo中,你可能不会遇见这个需求,当页面很多,组件很多的时候,你会发现你的页面在首次加载的时候,异常的慢,这个是因为vue首次加载的时候把可能一开始看不见的组件也一次加载了,这个时候就需要对页面优化了,就需要异步组件了。如何去写异步组件呢,实际上很简单,只需要在你的路由index,js里加上require就可以了,像下面这样,这也是所谓的按需加载组件的实现原理。
{
path: '/home',
name: 'Home',
component: function(resolve){
require(['@/views/home'], resolve)
}
}
第二种:直接引入const Foo = () => import('./Foo.vue')官网推荐
21 active-class是哪个组件的属性
active-class是vue-router模块的router-link组件中的属性,用来做选中样式的切换;
22 scss是什么?在vue.cli中的安装使用步骤是?有哪几大特性?
答:scss是css的预编译。
使用步骤:
第一步:先装css-loader、node-loader、sass-loader等加载器模块
第二步:在build目录找到webpack.base.config.js,在那个extends属性中加一个拓展.scss
第三步:在同一个文件,配置一个module属性
第四步:然后在组件的style标签加上lang属性 ,例如:lang=”scss”
特性:
可以用变量,例如($变量名称=值);
可以用混合器,例如()
可以嵌套
23 vue强制(主动)更新数据
有的时候给对象添加或删除改变属性和值的时候,虽然可以改变属性,但是不会触发视图更新
原因是:受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。
这时候我们用this.$set(this.data,”key”,value’)就可以更新了
正确写法:this.$set(this.data,”key”,value’)
mounted () {
this.$set(this.student,"age", 24)
}
24 vue-router 路由 模式的区别
Vue-router共有两种模式hash模式和history模式(默认是hash模式)
区别在与hash模式里有#号,history没有
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。
所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
History:方法:
history.go(-3);//后退3次
history.go(2);//前进2次
history.go(0);//刷新当前页面
history.back(); //后退
history.forward(); //前进
Hash:
this.$router.go()负数为后退正数为前进
this.$router.back()后退
this.forward()前进
Vue的优缺点:
Vue.js的特性如下:
1.轻量级的框架
2.双向数据绑定
3.指令
4.插件化
优点: 1. 简单:官方文档很清晰,比 Angular 简单易学。
2. 快速:异步批处理方式更新 DOM。
3. 组合:用解耦的、可复用的组件组合你的应用程序。
4. 紧凑:~18kb min+gzip,且无依赖。
5. 强大:表达式 & 无需声明依赖的可推导属性 (computed properties)。
6. 对模块友好:可以通过 NPM、Bower 或 Duo 安装,不强迫你所有的代码都遵循 Angular 的各种规定,使用场景更加灵活。
缺点: 1. 新生儿:Vue.js是一个新的项目,没有angular那么成熟。
2. 影响度不是很大:google了一下,有关于Vue.js多样性或者说丰富性少于其他一些有名的库。
3. 不支持IE8:
React的优缺点:
React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。
React特性如下:
1.声明式设计:React采用声明范式,可以轻松描述应用。
2.高效:React通过对DOM的模拟,最大限度地减少与DOM的交互。
3.灵活:React可以与已知的库或框架很好地配合。
优点: 1. 速度快:在UI渲染过程中,React通过在虚拟DOM中的微操作来实现对实际DOM的局部更新。
2. 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。
3. 模块化:为你程序编写独立的模块化UI组件,这样当某个或某些组件出现问题是,可以方便地进行隔离。
4. 单向数据流:Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。
5. 同构、纯粹的javascript:因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。
6. 兼容性好:比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏。
缺点: 1. React本身只是一个V而已,并不是一个完整的框架,所以如果是大型项目想要一套完整的框架的话,基本都需要加上ReactRouter和Flux才能写大型应用。
25.vue的this.$route和this.$router的区别及使用场景
通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由
可以理解为:
this.$router 相当于一个全局的路由器对象,包含了很多属性和对象(比如 history 对象),任何页面都可以调用其 push(), replace(), go() 等方法。
this.$route 表示当前路由对象,每一个路由都会有一个 route 对象,是一个局部的对象,可以获取对应的 name, path, params, query 等属性。
26.v-model如何实现
v-mode实现原理
27.vue路由传参params,query的区别
params刷新数据会消失(不拼接) query传递的参数会显示在url后面?id=?(以问号拼接出来)
详细用法:vue路由传参
28.v-if和v-for的优先级那个高?
当 v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级,这意味着 v-if
将分别重复运行于每个 v-for
循环中。
用法:可以将 v-if
置于外层元素或者直接写成计算属性
29.v-show和v-if的区别,及使用场景
v-if 的特点:每次都会重新删除或创建元素
v-show 的特点: 每次不会重新进行DOM的删除和创建操作,只是切换了元素的 display:none 样式 -->
v-if 有较高的切换性能消耗
v-show 有较高的初始渲染消耗
如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show
如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if