vue.js的两个核心是什么?
- 数据驱动(双向数据绑定)核心是VM,即ViewModel,保证数据和视图的一致性
- 组件系统
Vue双向数据绑定的原理
- Vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发给订阅者,触发相应的监听回调
请说出vue几种常用的指令
- v-if:根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。
- v-show:根据表达式之真假值,切换元素的 display CSS 属性。
- v-for:循环指令,基于一个数组或者对象渲染一个列表,vue 2.0以上必须需配合 key值 使用。
- v-bind:动态地绑定一个或多个特性,或一个组件 prop 到表达式。
- v-on:用于监听指定元素的DOM事件,比如点击事件。绑定事件监听器。
- v-model:实现表单输入和应用状态之间的双向绑定
- v-pre:跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
- v-once:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能
v-if 和 v-show 有什么区别
相同点
- 动态显示DOM元素。
区别
- v-if 是 真正 的 条件渲染,有更高的切换消耗,v-if适合运行时条件很少改变时使用
- v-show 只是简单地切换元素的 CSS 属性display。有更高的初始消耗,v-show适合频繁切换
vue常用的修饰符
- .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 } 模式添加侦听器
vue中 key 值的作用
- 唯一性,用于 管理可复用的元素
什么是$nextTick?
- 因为Vue的异步更新队列,$nextTick是用来知道什么时候DOM更新完成的。
Vue 组件中 data 为什么必须是函数?
- 因为组件是共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象,返回一个唯一的对象,不要和其他组件共用一个对象
v-for 与 v-if 的优先级
- v-for的优先级比v-if更高
- 永远不要把 v-if 和 v-for 同时用在一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)
- 如果避免出现这种情况,则在外层嵌套 template (页面渲染不生成dom节点),再这一层进行 v-if 判断,然后再内部进行 v-for 循环
<template v-if="isShow">
<p v-for="item in items">
</template>
vue中组件之间调用
vue中子组件调用父组件的方法
- 在子组件中通过'$emit'触发 当前实例上的 自定义事件。
- this.$emit('func',this.msg) (fuc是父组件中的函数,this.msg是传递给父组件的值)
父组件给子组件通过props传值
vue父组件调用子组件中的方法
- 在父组件中:首先要引入子组件 import Child from './child';
- 是在父组件中为子组件添加一个占位,ref="mychild"是子组件在父组件中的名字
- 父组件中 components: {} 是声明子组件在父组件中的名字
- 在父组件的方法中调用子组件的方法,很重要 this.$refs.mychild.parentHandleclick("hello");
Vue组件通讯方式
- props / $emit 适用 父子组件通信
- ref 与 children 适用 父子组件通信
- on 适用于 父子、隔代、兄弟组件通信
- listeners 适用于 隔代组件通信
- provide / inject 适用于 隔代组件通信
- Vuex 适用于 父子、隔代、兄弟组件通信
Vue中$set()的作用
- 给对象添加新的属性。如果视图不能更新的话用set 是因为Vue无法监听普通的新增属性的变化。
Axios
-Axios 是一个基于 promise 的 HTTP 库,可以在浏览器和 node.js 中运行
- 特性
1.从浏览器中创建 XMLHttpRequests 2.从 node.js 创建 http 请求 3.支持 Promise API 4.拦截请求和响应 5.转换请求数据和响应数据 6.取消请求 7.自动转换 JSON 数据 8.客户端支持防御 XSRF
- 安装方法
npm install axios - 引入(一般在封装接口的js文件中引入)
import axios from 'axios'; - 搭配UI框架如:iview、vant、elementUI等
vue中的跨域问题处理
- 为什么会出现跨域呢?
不满足同源策略:协议+域名+端口一致
- 解决跨域
在vue项目中找到vue.config.js文件中devServer配置
vue-router有哪几种导航钩子( 导航守卫 )?
- 全局守卫: router.beforeEach
- 全局解析守卫: router.beforeResolve
- 全局后置钩子: router.afterEach
- 路由独享的守卫: beforeEnter
- 组件内的守卫: beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave
vue-router路由的两种模式
- vue-router路由提供了两种路由模式:hash模式和history模式。
- hash模式:在浏览器中符号“#”,#以及#后面的字符称之为 hash, 用 window.location.hash 读取
- 在vue的router中,通过修改vueRouter的mode属性来决定使用history还是hash。默认为hash模式。
vue 路由跳转
- 标签跳转 router-link
<li >
<router-link to="user">点击验证动画效果 </router-link>
</li>
- 事件跳转 this.$router.push()
query 传参,相当于get请求,页面跳转时参数会在地址栏中显示
this.$router.push({
path:'/user',
query:{
id:this.id
}
})
params 传参,相当于post请求,页面跳转时参数不会在地址栏中显示,通过this.$route.params.id获取
this.$router.push({
path:'/user',
params:{
id:this.id
}
})
- this.$router.replace{path:'/user'} (描述:同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录)
- this.$router.go(n) 相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面
- this.router.forward() 前进一步
- this.router.back() 回退一步
vuex(状态管理器的使用)
- 安装
npm install vuex --save - 在 src/文件下面创建store文件创建index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
//挂载Vuex
Vue.use(Vuex)
//创建VueX对象
const store = new Vuex.Store({
//state定义属性
state: {
count: 0,
},
//只有mutations才能变更store中的数据,不能在mutations函数中执行异步操作
mutations: {
addition(state) {
state.count++
},
addition2(state, step) {
state.count += step
},
subtraction(state) {
state.count--
},
subtraction2(state, step) {
state.count -= step
}
},
//actions用于异步操作,但是在action中要通过触发mutation的方式来变更数据
actions: {
addAsync(context) {
setTimeout(() => {
context.commit('addition')//addition是mutations中的函数
}, 1000)
},
addAsync2(context, step) {
setTimeout(() => {
context.commit('addition2', step)//addition是mutations中的函数
}, 1000)
},
subAsync(context) {
setTimeout(() => {
context.commit('subtraction')//addition是mutations中的函数
}, 1000)
},
subAsync2(context, step) {
setTimeout(() => {
context.commit('subtraction2', step)//addition是mutations中的函数
}, 1000)
},
},
//getters 不会修改state里面是数据,获取最新的数据
getters:{
shownum(state){
return '当前最新的值为【'+state.count+'】'
}
}
})
export default store
3.在main.js中引用
import store from './store'//引入store文件夹下面的index.js
webpack
webpack 中的 loader 的作用是什么
- webpack是基于 node 的,只能处理 JS和 JSON文件,loader 的作用是用来处理其他类型的文件(less\vue....等) 可以将 less 转成 css 文件,将 jsx处理成 JS文件,将其他版本的 ES 处理成浏览器能识别的 ES 版本
使用 webpack 时如何优化项目体积
- 使用用 uglyfly 进行代码压缩,使用 commonsChunk 分离第三方代码
webpack 中什么是 HMR,原理是什么
- HMR(Hot Module Replacement),热更新又称热替换,基于 webpack-dev-server。 第一步:webpack 对文件系统进行 watch 打包到内存中 第二步:devServer 通知浏览器端文件发生改变,在这一阶段,sockjs 是服务端和浏览器端之间的桥梁,在启动 devServer 的时候,sockjs 在服务端和浏览器端建立了一个 webSocket 长连接,以便将 webpack 编译和打包的各个阶段状态告知浏览器 第三步:webpack-dev-server/client 接收到服务端消息做出响应 第四步:webpack 接收到最新 hash 值验证并请求模块代码 第五步:HotModuleReplacement.runtime 对模块进行热更新 第六步:调用 accept 方法,及时将新后的内容插入到页面中
vue 项目中如何在页面刷新的状态下保留数据
- 页面刷新的同时数据同步更新到LocalStorage/SessionStorage里面
- 路由传值
vue中watch,computed 和methods的区别
计算属性computed :
- 支持缓存,只有依赖数据发生改变,才会重新进行计算
- 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
- computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
- 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
- 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
监听属性watch:(需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用)
- 不支持缓存,数据变,直接会触发相应的操作
- watch支持异步
- 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
- 当一个属性发生变化时,需要执行对应的操作;一对多;
- 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,
- immediate:组件加载立即触发回调函数执行, deep: 深度监听,复杂类型的数据时使用,例如数组中的对象改变。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
Methods
- Methods是挂载到vue实例所有方法的集合
子组件可以直接改变父组件的数据吗?
- 子组件不可以直接改变父组件的数据。这样做主要是为了维护父子组件的单向数据流。每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。如果这样做了,Vue 会在浏览器的控制台中发出警告
- Vue提倡单向数据流,即父级 props 的更新会流向子组件,但是反过来则不行。这是为了防止意外的改变父组件状态,使得应用的数据流变得难以理解,导致数据流混乱。如果破坏了单向数据流,当应用复杂时,debug 的成本会非常高
- 只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改.