1、MVVM的理解
MVVM 是 Model-View-ViewModel 的缩写。
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View 代表UI 组件,它负责将数据模型转化成UI 展现出来。
ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理
2、vue父子组件之间的传值
父向子传值:父组件绑定自定义属性,子元素用props属性以数组的形势接收自定义属性,
子向父传值:父组件绑定自定义事件,方法的参数即为子组件传来的值,子组件用$emit触发父元素的自定义事件,第一个参数为自定义事件名,后面的参数即为要传的值
3、vue生命周期函数
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
4、自定义指令
在某些场景下需要对普通DOM元素进行操作的时候,如图片加载前的默认背景图展示,
<div id="app2" class="demo">
<img src="../assets/image/bg.png" alt="默认图" v-image="image.url">
</div>
<script>
Vue.directive("image", {//定义全局自定义指令
inserted: function(el, binding) {//钩子函数,被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
//el: 指令所绑定的元素 binding: 一个对象,指令后面绑定的值
//为了真实体现效果,用了延时操作
setTimeout(function(){
el.setAttribute("src", binding.value);
}, Math.random() * 1200)
}
})
new Vue({
el: "#app2",
data: {
image: {
url: "http://consumer-img.huawei.com/content/dam/huawei-cbg-site/greate-china/cn/mkt/homepage/section4/home-s4-p10-plus.jpg"
}
}
})
</script>
5、vue动态路由传值
$router
和$route
的区别:
$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
$router是“路由实例”对象包括了路由的跳转方法,钩子函数等
params传递参数 :
//params传参 使用name
this.$router.push({
name:'second',
params: {
id:'20180822',
name: 'query'
}
})
// => /second/20180822/query
//params接收参数
this.id = this.$route.params.id ;
this.name = this.$route.params.name ;
//路由
{
path: '/second/:id/:name',
name: 'second',
component: () => import('@/view/second')
}
query传递参数:
//query传参,使用path跳转
this.$router.push({
path:'second',
query: {
queryId:'20180822',
queryName: 'query'
}
})
// => /second?queryId=20180822&queryName=query
//query传参接收
this.queryName = this.$route.query.queryName;
this.queryId = this.$route.query.queryId;
//路由
{
path: '/second',
name: 'second',
component: () => import('@/view/second')
}
区别:
- params是路由的一部分,必须要在路由后面添加参数名。query是拼接在url后面的参数,没有也没关系。
- 二者还有点区别,直白的来说query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示。
6、Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
state:基本数据
getters:从基本数据派生的数据
mutations:提交更改数据的方法,同步!
actions:像一个装饰器,包裹 mutations,使之可以异步。
modules:模块化 Vuex
7、常用指令
v-html:渲染文本(能解析 HTML 标签)
v-text:渲染文本(统统解析成文本)
v-bind:绑定数据
v-once:只绑定一次
v-model:绑定模型
v-on:绑定事件
v-if v-show:条件渲染
8、 vue-cli 工程中每个文件夹和文件的用处
build 文件夹:存放 webpack 的相关配置以及脚本文件,在实际开发过程中只会偶尔用到 webpack.base.conf.js,配置 less、babel 等。
config 文件夹:常用到此文件夹下的 config.js (index.js) 配置开发环境的端口号,npm run build 命令打包生成静态资源的名称和路径、是否开启热加载或者设置生产环境的静态资源相对路径、是否开启 gzip 压缩等。
node_modules:存放 npm install 命令下载的开发环境和生产环境的各种依赖。
src文件夹 :工程项目的源码以及资源、包括页面图片、路由组件、路由配置、vuex、入口文件等。
其他文件:定义的一些项目信息,说明等等
9、hash与history
单页应用通过匹配不同的 url 路径, 从而加载不同的组件,vue-router有两种模式:
hash模式(默认)
通过改变#后面的值,可以通过hashchange事件监听
history模式
修改历史状态
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
切换历史状态
-
history.go(-2);//后退两次
-
history.back(); //后退
-
hsitory.forward(); //前进
区别:
- history模式下,pushState设置的新URL可以是与当前URL同源的任意URL,history模式则会将URL修改得就和正常请求后端的URL一样,如后端没有配置对应的路由处理,则会返回404错误
- hash模式下,你只能改变#后面的url片段。页面刷新时,因为不会请求#后面的内容,所以页面不会出现404错误
10、优化首屏加载速度
1、对于第三方js库的优化,分离打包(减小打包后的js的)
使用cdn引入第三方js,工具库也要按需引入, 在webpack的dev开发配置文件中, 加入如下参数,然后在需要使用依赖的地方 import 进来就可以
//key为依赖包名称,value是源码抛出来的全局变量。
externals: {
'element-ui': 'ELEMENT',
'vue': 'Vue',
'axios': 'axios',
'echarts': 'echarts',
'vue-router': 'VueRouter'
},
2、gzip压缩
安装compression-webpack-plugin, 配置 config/index.js, nginx开启 gzip 模式
3、vue-router使用懒加载
component: () => import("./pages/Index/Index")
4、关闭sourcemap
config/index.js中 productionSourceMap: false,
11、computed和watch的使用场景
computed:
当一个属性受多个属性影响的时候就需要用到computed
最典型的栗子: 购物车商品结算的时候
watch:
当一条数据影响多条数据的时候就需要用watch
栗子:搜索数据
12、vue双向绑定原理
vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时发布消息给订阅者,触发相应的监听回调。
13、assets和static的区别
运行npm run build时会将assets中放置的静态资源文件进行打包上传,static则会直接上传(可以放不需要压缩的js css)
14、vue常用的修饰符
.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);
.capture:与事件冒泡的方向相反,事件捕获由外到内;
.self:只会触发自己范围内的事件,不包含子元素;
.once:只会触发一次。
15、vue的两个核心点
数据驱动:ViewModel,保证数据和视图的一致性。
组件系统:应用类UI可以看作全部是由组件树构成的。
16、引进组件的步骤
在script的第一行用import引入路径(引入)
用component中写上组件名称(注册)
在template中引入组件(使用)
17、vue-router 有哪几种导航钩子
第一种:是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截,通过next决定往哪里跳转
第二种:组件内的钩子
第三种:单独路由独享组件
18、自定义过滤器
应用:如时间戳转换时间格式
<div id="app">
<input type="text" v-model="msg" />
{{msg| capitalize }}
</div>
var vm=new Vue({
el:"#app",
data:{
msg:''
},
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)
})
19、axios和ajax区别
ajax技术实现了网页的局部数据刷新,axios实现了对ajax的封装
优缺点:
ajax:
本身是针对MVC的编程,不符合现在前端MVVM的浪潮
基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案
JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务
axios:
从 node.js 创建 http 请求
支持 Promise API
客户端支持防止CSRF(跨站点请求伪造,在请求地址中添加 token 并验证,或者在 HTTP 头中自定义属性并验证)
提供了一些并发请求的接口(重要,方便了很多的操作)
20、slot
父组件向子组件插入DOM,DOM里的数据可以是父组件也可以是子组件的,DOM的位置由子组件的slot位置决定,DOM的样式由父组件决定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Child>
<!-- 不指定使用哪个插槽,则会进入默认插槽 -->
<div>父组件的一些东西,放入默认插槽里</div>
<!-- 指定使用child插槽 -->
<!-- slot-scope 来取得作用域插槽:data绑定的数据 -->
<template slot="child" slot-scope="scope">
<div>父组件的又一些东西,放入具名插槽里</div>
<div>{{scope.data}}</div>
</template>
</Child>
</div>
<template id="child">
<div>
<!-- 默认插槽 -->
<slot></slot>
<!-- 具名插槽 而且也是带数据的插槽-->
<slot name="child" :data="msg"></slot>
<div>子组件的一些东西</div>
</div>
</template>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data: {},
components: {
Child: {
template: '#child',
data() {
return {
msg: '子组件的数据'
}
}
}
}
})
</script>
</html>
21、export,export default,import,import()
1、export:
输出变量
// 1. 直接输出变量(方法、类)
export var m = 1;
export function multiply(x, y) {
return x * y;
};
// 2. 使用大括号指定所要输出的一组变量(方法、类)
var m = 1;
export { m };
// 3. as关键字重命名
// 重命名后,v2可以用不同的名字输出两次
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
1.export
语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
2.export
命令可以出现在模块的任何位置,只要处于模块顶层就可以。
2、export default:直接输出变量的值而不是名字,引入的时候指定名字
// 默认输出一个函数
export default function () {
console.log('foo');
}
// 引用并指定名字
import customName from './export-default';
3、import:
引入变量
// 1. 引入变量(方法、类)-(逐一加载)
import { firstName, lastName, year } from './profile.js';
// 2. as关键字重命名
import { lastName as surname } from './profile.js';
// 3. 整体加载
import * as circle from './circle';
- 引入变量只读,引入对象属性可改写
- from后面是文件路径(相对路径、绝对路径均可,可省略.js;模块名,已配置模块位置)
import
命令提升至顶部先执行(编译阶段执行)import
命令静态执行,不能使用表达式和变量- 重复执行同一句
import
命令,只会执行一次
4、import() 动态加载
import('./myModule.js')
.then(({export1, export2}) => {
// ...
});
import()
和import
主要区别为前者是动态加载。 import()
返回一个Promise
对象,import()
加载模块成功以后,这个模块会作为一个对象,当作then方法的参数。 import()
类似于Node的require
方法,区别主要是前者是异步加载,后者是同步加载 import()
通常用于按需加载、条件加载、动态的模块路径
22、sync修饰符
子组件修改父组件的某个数据时可以用sync这个语法糖