vue知识点
1、对于Vue是一套渐进式框架的理解
Vue核心功能是一个视图模板引擎,可以通过添加组件系统、客户端路由、大规模状态管理来构建一个完整的框架。可以在核心功能的基础上任意选用其他的部件。这就是“渐进式”,就是Vue的使用方式。
2、vue.js的两个核心是什么?
数据驱动、组件系统。
3、请问 v-if 和 v-show 有什么区别?
v-if判断条件是否渲染,是惰性的,初始渲染时条件为假时什么也不做;v-show是 display: block/none;元素始终都会渲染;在项目中如果需要频繁的切换则使用v-show较好,运行条件很少改变,则使用v-if。
4、vue常用的修饰符
.prevent 提交事件不再重载页面;
.stop 阻止单击事件冒泡;
.self 当事件发生在该元素本身而不是子元素时触发;
.capture 添加事件监听器时使用事件捕获模式;
.once 只会触发一次
按键修饰符
:keyup.enter
:keyup.tab
5、v-on可以监听多个方法吗? 可以。
6、vue中 key 值的作用
v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的唯一 id。
主要是为了高效的更新虚拟DOM。
7、vue-cli工程升级vue版本
手动修改 package.json 里面vue的版本,同时修改 vue-template-compiler 为相同的版本;后者在devDependencies里面,然后npm install。
8、vue事件中如何使用event对象? @click=”EventName($event)”
9、$nextTick的使用
在修改数据之后立即使用这个方法,获取更新后的 DOM。
10、Vue 组件中 data 为什么必须是函数
每用一次组件,就会有一个新实例被创建。每个实例可以维护一份被返回对象的独立的拷贝,每个对象都是独立互不影响的。
11、v-for 与 v-if 的优先级
v-for 具有比 v-if 更高的优先级。
v-if 将分别重复运行于每个 v-for 循环中。vue风格指南提示永远不要把 v-if 和 v-for 同时用在同一个元素上。
12、vue中子组件调用父组件的方法
第一种:this.$parent.xxx;
第二种:通过props传递父组件函数名,子组件接受,接受类型为Function;
第三种:创建eventBus。
13、vue中 keep-alive 组件的作用
keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。
include – 字符串或正则表达式,只有名称匹配的组件会被缓存;
exclude 反之亦然。 include=”a,b” :include=”/a|b/” :include=”[‘a’, ‘b’]”
14、vue中如何编写可复用的组件?
- 规范化命名:组件的命名应该跟业务无关,而是依据组件的功能命名。
数据扁平化:定义组件接口时,尽量不要将整个对象作为一个 prop 传进来。每个 prop 应该是一个简单类型的数据。这样做有下列几点好处:
(1) 组件接口清晰。
(2) props 校验方便。
(3) 当服务端返回的对象中的 key 名称与组件接口不一样时,不需要重新构造一个对象。扁平化的 props 能让我们更直观地理解组件的接口。
- 可复用组件只实现 UI 相关的功能,即展示、交互、动画,如何获取数据跟它无关,因此不要在组件内部去获取数据。
- 可复用组件应尽量减少对外部条件的依赖。
- 组件在功能独立的前提下应该尽量简单,越简单的组件可复用性越强。
- 组件应具有一定的容错性。
15、什么是vue生命周期和生命周期钩子函数?
Vue 实例从创建到销毁的过程,就是生命周期。
从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
16、vue生命周期钩子函数有哪些?
beforeCreate(创建前) 在数据观测和初始化事件还未开始
created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来;
beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上;
mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互;
beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程;
updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用;
beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用;
destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
17、vue如何监听键盘事件中的按键?
监听keyup事件并添加按键修饰符,对一些常用按键vue提供了别名,或者使用keyCode,vue也支持复合按键。
18、vue更新数组时触发视图更新的方法
Vue.set(arr, key, value) Vue.set(object, key, value)
19、vue中对象更改检测的注意事项
Vue 不能检测对象属性的添加或删除;不能动态添加根级别的响应式属性。
使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性。
20、解决非工程化项目初始化页面闪动问题
vue页面在加载的时候闪烁花括号{}},v-cloak指令和css规则如[v-cloak]{display:none}一起用时,这个指令可以隐藏未编译的Mustache标签直到实例准备完毕。
/*css样式*/
[v-clock] {
display: none;
}
21、v-for产生的列表,实现active的切换
<ul class="ul" >
<li v-on:click="currentIndex = index"
class="item"
v-bind:class="{clicked: index === currentIndex}"
v-for="(items, index) in arr">
<a>{{items}}</a>
</li>
</ul>
data() {
return{
currentIndex: 0
}
}
22、v-model语法糖的组件中的使用
1:用于表单上数据的双向绑定;
2:修饰符:
.lazy- 取代input监听change事件
.number- 输入字符串转为数字
.trim- 输入首尾空格过滤
23、十个常用的自定义过滤器
// 全局方法 Vue.filter() 注册一个自定义过滤器
Vue.filter("sum", function(value) {
return value + 4;
});
// 局部
new Vue({
el: ".test",
data: {
message:12
},
filters: {
sum: function (value) {
return value + 4;
}
}
})
24、vue等单页面应用及其优缺点
优点——数据驱动、组件化、轻量简洁高效,通过尽可能简单的API实现响应的数据绑定和组合的视图组件;
缺点:不支持低版本的浏览器,不利于SEO优化,可以使用服务器端渲染,首次加载耗时长。
25、什么是vue的计算属性?
在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。
计算属性基于它们的依赖进行缓存的;只在相关依赖发生改变时它们才会重新求值。
31、计算属性的缓存和方法调用的区别
两种方式的最终结果确实是完全相同的。
不同的是计算属性是基于它们的依赖进行缓存的,只在相关依赖发生改变时它们才会重新求值。
只要相关依赖还没有发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数
如果不希望有缓存,请用方法来替代。
26、vue-cli提供的几种脚手架模板
vue-cli的脚手架项目模板有webpack-simple 和 webpack;
区别在于webpack-simple 没有包括Eslint 检查等功能。
27、vue父组件如何向子组件中传递数据? 通过父组件v-bind传递数据子组件props接收数据
28、vue-cli开发环境使用全局常量
①少量
Vue.prototype.baseUrl = function () {
return 'https://segmentfault.com/';
};
Vue.prototype.getTitle = {
title:'',
isBack: true,
isAdd: false,
};
②配置文件形式
在项目的src 目录里面 新建一个 lib目录,lib目录里创建一个 config.js文件。
export default {
install(Vue,options) {
Vue.prototype.baseUrl = function () {
return '111';
};
Vue.prototype.getTitle = {
title:'',
isBack: true,
isAdd: false,
};
Vue.prototype.showFootTab = {
isShow:false,
active:0,
}
}
最后导入
import config from './lib/config.js';
Vue.use(config);
使用
<template>
<div>
{{getTitle.title}}
</div>
</template>
this.getTitle
29、vue-cli生产环境使用全局常量
30、vue弹窗后如何禁止滚动条滚动?
/***滑动限制***/
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);
}
// 如果不是Vue,可以直接给html设置overflow:hidden
32、vue-cli中自定义指令的使用
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}![图片描述][1]
}
}
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
vue-router
1、vue-router如何响应 路由参数 的变化?
当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。同时意味着组件的生命周期钩子不会再被调用。
复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
}
}
2、完整的 vue-router 导航解析流程
导航被触发。
在失活的组件里调用离开守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
3、vue-router有哪几种导航钩子( 导航守卫 )?
全局的, 单个路由独享的, 组件级的。
全局守卫:
router.beforeEach router.beforeResolve(2.5+) router.afterEach
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
router.afterEach((to, from) => {
// 这些钩子不会接受 next 函数也不会改变导航本身: ...
})
路由独享的守卫: beforeEnter 这些守卫与全局前置守卫的方法参数是一样的。
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
组件内的守卫
beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next(vm => {
// 通过 `vm` 访问组件实例
})
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
4、vue-router的几种实例方法以及参数传递
编程式导航
this.$router.push({ name: 'news', params: { userId: 123 }}); // this.$route.params.userId
this.$router.push({ path: '/news', query: { userId: 123 }}); // this.$route.query.userId
this.$router.replace();
声明式导航
<router-link :to="{ name: 'news', params: { userId: 1111}}">click to news page</router-link>
<router-link :to="{ path: '/news', query: { userId: 1111}}">click to news page</router-link>
5、vue-router的动态路由匹配以及使用
需要把某种模式匹配到的所有路由,全都映射到同个组件
const User = {
template: '<div>User{{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]
})
复用组件时,想对路由参数的变化作出响应的话,使用watch (监测变化) $route 对象
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
}
}
想匹配任意路径,我们可以使用通配符 (*)
{
// 会匹配所有路径
path: '*'
}, {
// 会匹配以 `/user-` 开头的任意路径
path: '/user-*'
}
6、vue-router如何定义嵌套路由?
在router.js使用children数组来定义子路由,并在模板中使用<router-view>定义嵌套路由。
如果没有匹配到合适的子路由,可以提供一个 空的 子路由
routes: [
{
path: '/user/:id', component: User,
children: [
// 当 /user/:id 匹配成功,
// UserHome 会被渲染在 User 的 <router-view> 中
{ path: '', component: UserHome },
// ...其他子路由
]
}
]
7、<router-link></router-link>组件及其属性
<router-link> 组件支持用户在具有路由功能的应用中 (点击) 导航。
通过 to 属性指定目标地址,默认渲染成带有正确链接的 <a> 标签,可以通过配置 tag 属性生成别的标签。
to:
<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染结果 -->
<a href="home">Home</a>
<!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind:to="'home'">Home</router-link>
<!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link>
<!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link>
<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
<!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
replace: 会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。
<router-link :to="{ path: '/abc'}" replace></router-link>
append: 在当前 (相对) 路径前添加基路径
tag: 渲染成某种标签
active-class: 设置 链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。
8、vue-router实现路由懒加载( 动态加载路由 )
component: () => import('comp/AlbumlibMore')
9、vue-router路由的两种模式
vue-router 默认 hash 模式
使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
HTML5 History 模式
充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
要玩好,还需要后台配置支持;
因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404
10、history路由模式与后台的配合
在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面;然后在给出一个 404 页面。
vuex
1、什么是vuex?
专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。
在main.js引入store,注入。新建了一个目录store,export 。
场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车
2、使用vuex的核心概念
state => 基本数据
getters => 从基本数据派生的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex,当应用变得非常复杂时,store 对象会变得臃肿不堪。
3、vuex在vue-cli中的应用
单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车
4、组件中使用 vuex 的值和修改值的地方?
getters,actions(异步),mutations(同步)
5、在vuex中使用异步修改
import * as types from './mutation-types';
export const selectPlay = function ({commit}, {list, index}) {
commit(types.SET_LIST, list);
commit(types.SET_INDEX, index);
commit(types.SET_FULL, true);
};
使用
import {mapActions} from 'vuex';
...mapActions([
'selectPlay'
])
this.selectPlay({
list: lists.concat([]),
index: indexs
});
6、pc端页面刷新时实现vuex缓存
办法一:将vuex中的数据直接保存到浏览器缓存中(sessionStorage、localStorage、cookie)
办法二:在页面刷新的时候再次请求远程数据,动态更新vuex数据
分析:
办法一的缺点是不安全,不适用大数据量的存储;
办法二适用于少量的数据,并且不会出现网络延迟;
http请求
1、Promise对象是什么?
是一个构造函数,有all、reject、resolve方法;原型上有then、catch方法。
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,
分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。
缺点
1.无法取消promise,一旦创建就立即执行,无法中途取消
2.如果不设置回调函数,promise内部抛出错误,不会反映到外部
2、axios、fetch与ajax有什么区别?
ajax
本身是针对MVC的编程,不符合现在前端MVVM的浪潮
基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案
JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)
axios
基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,
1.从浏览器中创建 XMLHttpRequest
2.支持 Promise API
3.客户端支持防止CSRF
4.提供了一些并发请求的接口(重要,方便了很多的操作)
5.从 node.js 创建 http 请求
6.拦截请求和响应
7.转换请求和响应数据
8.取消请求
9.自动转换JSON数据
fetch
是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。Fetch是基于promise设计的。
参数有点像jQuery ajax。
fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
3、什么是JS的同源策略和跨域问题?
同源是指两个页面具有相同的协议,主机(域名),端口。主要针对的是js中的XMLHttpRequest请求
4、如何解决跨域问题?
使用ajax发送请求时添加jsonp参数
dataType: "jsonp",
jsonp: "callback",
//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",
//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数
使用axios发送请求,使用代理
config => index.js => module.exports => dev => proxyTable
'/api': {
changeOrigin: true,
target: 'url1',
bypass: function (req, res, proxyOptions) {
req.headers.referer = 'url2';
req.headers.host = 'host';
},
pathRewrite: {
'^/api': ''
}
},
5、vue-cli中如何使用JSON数据模拟?
vue-cli mock模拟数据+json-server
json server 工具
npm install json-server --save //json server
npm install axios --save //使用axios发送请求
新建 xx.json 文件
终端输入
json-server db.json --port 3000 //(端口)
打开package.json => scripts 中配置一个mock
"mock": "json-server db.json --port 3003"
npm run mock
6、vue-cli中http请求的统一管理。
7、axios有什么特点?
1.从浏览器中创建 XMLHttpRequest
2.支持 Promise API
3.客户端支持防止CSRF
4.提供了一些并发请求的接口(重要,方便了很多的操作)
5.从 node.js 创建 http 请求
6.拦截请求和响应
7.转换请求和响应数据
8.取消请求
9.自动转换JSON数据
UI样式
1、.vue组件的scoped属性的作用
表示它的样式作用于当下的模块,很好的实现了样式私有化的目的,这是一个非常好的机制。
同时样式将会变得不易修改。
2、如何让CSS只在当前组件中起作用?
在style标签上 使用scoped属性
3、vue-cli中常用的UI组件库
ElementUI mint-ui vux
4、如何适配移动端?【 经典 】
使用postcss+vw单位
app,pc俩个路由,app代表手机端,pc代表移动端点击跳转或者进入页面加载判断
5、移动端常用媒体查询的使用
移动端1像素边框的问题
图片几倍的问题
bg-image($url)
background-image: url($url + "@2x.png")
@media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3)
background-image: url($url + "@3x.png")
6、垂直居中对齐
使用flex布局
display: flex;
align-items: center;
使用display 和 vertical-align
display: table-cell;
vertical-align: middle;
line-height+margin: 0 auto--元素定宽
父元素
position: relative;
子元素
position: absolute;
top: 50%;
transform: translate(0, -50%);
子元素
position: absolute;
top: 0;
bottom: 0;
margin: auto;
display: flex;
align-items: center;
line-height
7、vue-cli中如何使用背景图片?
1、找到 build/utils.js,增加一行代码即可: publicPath:"../../"
2、
8、使用表单禁用时移动端样式问题
9、多种类型文本超出隐藏问题
ellipsis()
overflow: hidden
white-space: nowrap
text-overflow: ellipsis
ellipsis-clamp($num)
overflow: hidden
text-overflow: ellipsis
display: -webkit-box
-webkit-line-clamp: $num
-webkit-box-orient: vertical
常用功能
1、vue中如何实现tab切换功能?
2、vue中如何利用 keep-alive 标签实现某个组件缓存功能?
3、vue中实现切换页面时为左滑出效果
4、vue中父子组件如何相互调用方法?
5、vue中央事件总线的使用
混合开发
1、vue如何调用 原生app 提供的方法?
2、原生app 调用 vue 提供的方法,并将值传递到 .vue 组件中
生产环境
1、vue打包命令是什么?
npm run build
2、vue打包后会生成哪些文件?
生成dist文件夹,里面有index.html和static文件夹, 包含css、js、img
3、如何配置 vue 打包生成文件的路径?
在 config => index.js => module.exports => build
4、vue如何优化首屏加载速度?
异步组件 () => import('vue');
img-lazyLoad
MVVM设计模式
1、MVC、MVP与MVVM模式
MVC全名是**Model View Controller**,模型(model)-视图(view)-控制器(controller)的缩写,一种架构模式;
view操作会触发controller去改变model,然后model再去改变视图
model:应用程序中处理数据逻辑的一部分,通常用来模型对象对数据库的存存取等操作
view:视图部分,通常指jsp、html等用来对用户展示的一部分
controller:控制层通常用来处理业务逻辑,负责从试图读取数据,并向模型发送数据
mvvm 即 **Model-View-ViewModel**,即模型-视图-视图模型;一种设计思想;本质上就是MVC 的改进版。
主要目的是分离视图(View)和模型(Model)。
【模型】指的是后端传递的数据。
【视图】指的是所看到的页面。
【视图模型】mvvm模式的核心,它是连接view和model的桥梁。
一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。
二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。
这两个方向都实现的,我们称之为数据的双向绑定。
低耦合、可重用性、独立开发
2、MVC、MVP与MVVM的区别
3、常见的实现MVVM几种方式
- 数据劫持(vue):通过Object.defineProperty() 去劫持数据每个属性对应的getter和setter;
- 脏值检测(angular):通过特定事件比如input,change,xhr请求等进行脏值检测;
- 发布-订阅模式(backbone):通过发布消息,订阅消息进行数据和视图的绑定监听。
链接描述
4、Object.defineProperty()方法
Object.defineProperty(obj, prop, descriptor)
会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
obj -- 要在其上定义属性的对象
prop -- 要定义或修改的属性的名称。
descriptor --- 将被定义或修改的属性描述符。
var o = {}; // 创建一个新对象
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
value : 37,
writable : true, // 为true时,value才能被赋值运算符改变。默认为 false。
enumerable : true, // enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
configurable : true // 为 true 时,该属性描述符才能够被改变,默认为 false。
});
5、实现一个自己的MVVM(原理剖析)
MVVM设计代码–1
MVVM设计代码–2
MVVM设计代码–3
6、 ES6中类和定义
传统的javascript中只有对象,没有类的概念。
它是基于原型的面向对象语言原型对象特点就是将自身的属性共享给新对象。
class Person{//定义了一个名字为Person的类
constructor(name,age){//constructor是一个构造方法,用来接收参数
this.name = name;//this代表的是实例对象
this.age=age;
}
say(){//这是一个类的方法,注意千万不要加上function
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
}
var obj=new Person("laotie",88);
console.log(obj.say());//我的名字叫laotie今年88岁了
7、JS中的文档碎片
document.createDocumentFragment() 一个容器,用于暂时存放创建的dom元素
将需要添加的大量元素 先添加到文档碎片中,再将文档碎片添加到需要插入的位置,大大 减少dom操作,提高性能
for(var i=100; i>0; i--){
var elem = document.createElement('div');
document.body.appendChild(elem); // 放到body中
}
// 文档碎片:(操作1次dom)
var df = document.createDocumentFragment();
for(var i=100; i>0; i--){
var elem = document.createElement('div');
df.appendChild(elem);
}
// 最后放入到页面上
document.body.appendChild(df);
8、解构赋值
是一种 Javascript 表达式,将值从数组,或属性从对象,提取到不同的变量中。
对象和数组逐个对应表达式,或称对象字面量和数组字面量
var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]
({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20
// Stage 4(已完成)提案中的特性
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}
9、Array.from与Array.reduce
Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。
reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
Array.from(arrayLike[, mapFn[, thisArg]])
arrayLike 想要转换成数组的伪数组对象或可迭代对象。
mapFn (可选参数) 如果指定了该参数,新数组中的每个元素会执行该回调函数。
thisArg (可选参数) 可选参数,执行回调函数 mapFn 时 this 对象。
返回值 一个新的数组实例
arr.reduce(callback[, initialValue])
reduce
10、递归的使用
递归就是在程序中函数直接或间接调用自己;
如果有个函数foo,如果他是递归函数,到最后问题还是转换为函数foo的形式;
递归的步骤(技巧)
1. 假设递归函数已经写好
2. 寻找递推关系
3. 将递推关系的结构转换为递归体
4. 将临界条件加入到递归体中
求1-100的和
function sum(n){
if(n==1) return 1;
return sum(n-1) + n;
// return arguments.callee(n-1) + n;
}
11、Obj.keys()与Obj.defineProperty
Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。
Object.defineProperty(obj, prop, descriptor)
Object.keys() 用于枚举一个对象的属性名,返回数组。
var x = {};x.a = “a”;x.b = “b”;Object.keys(x);//=>[“a”, “b”]
MDN-Object.defineProperty()
Object.keys()
12、发布-订阅模式
发布—订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
可以广泛应用于异步编程中,这是一种替代传递回调函数的方案。
观察者模式代码示范1
观察者模式代码示范2
13、实现MVVM的思路分析
1、数据劫持(vue):通过Object.defineProperty() 去劫持数据每个属性对应的getter和setter
2、脏值检测(angular):通过特定事件比如input,change,xhr请求等进行脏值检测。
3、发布-订阅模式(backbone):通过发布消息,订阅消息进行数据和视图的绑定监听。
1、实现一个Observer,对数据进行劫持,通知数据的变化
2、实现一个Compile,对指令进行解析,初始化视图,并且订阅数据的变更,绑定好更新函数
3、实现一个Watcher,将其作为以上两者的一个中介点,在接收数据变更的同时,让Dep添加当前Watcher,并及时通知视图进行
vue-cli
1、vue-cli 工程常用的 npm 命令有哪些?
$ npm install vue-cli //1
$ vue init webpack vue-project //2
$ cd vue-project //3
$ npm install //4
$ npm run dev
2、请说出vue-cli工程中每个文件夹和文件的用处
3、config文件夹 下 index.js 的对于工程 开发环境 和 生产环境 的配置
module.exports => dev => proxyTable 开发时请求代理
module.exports => port 开发时使用端口
module.exports => build => 规定打包后文件的结构以及名称
4、详细介绍一些 package.json 里面的配置
name: 项目名称,
version: 版本号,
description: 项目说明,
author: 作者信息,
dependencies: 开发环境和生产环境都需要的依赖包
devDependencies: 生产环境的依赖包
5、npm是什么?
Node.js的包管理工具。
因为我们在Node.js上开发时,会用到很多别人写的JavaScript代码。如果我们要使用别人写的某个包,每次都根据名称搜索一下官方网站,下载代码,解压,再使用,非常繁琐。于是一个集中管理的工具应运而生:大家都把自己开发的模块打包后放到npm官网上,如果要使用,直接通过npm安装就可以直接用,不用管代码存在哪,应该从哪下载。
npm cache clean --force
// 删除缓存目录下的所有数据。从npm@5开始为保证缓存数据的有效性和完整性,需要将加上 --force 参数
npm cache verify
// 验证缓存数据的有效性和完整性,清理垃圾数据。
源码剖析
1、vue内部与运行机制:
Vue.js 全局运行机制
响应式系统的基本原理
什么是 Virtual DOM?
如何编译template 模板?
diff算法
批量异步更新策略及 nextTick 原理?
proxy代理?
2、vuex工作原理详解
Vue.mixin
Vue.use
深入拓展
1、vue开发命令 npm run dev 输入后的执行过程
npm run XXX是执行配置在package.json中的脚本,比如:
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
// --host 0.0.0.0
"start": "node build/dev-server.js",
"build": "node build/build.js"
},
这里就是执行了 node build/webpack.dev.conf.js文件,这个文件直接或间接引用了App.vue main.js文件
2、vue的服务器端渲染
服务器端渲染讲解
代码示范
代码示范-SSR
3、从零写一个npm安装包
4、vue-cli中常用到的加载器
vue-router vuex vue-lazyload axios
babel-runtime babel-polyfill jsonp eslint
移动端better-scroll fastclick
样式stylus stylus-loader
5、webpack的特点
- 代码拆分(支持异步模块加载)
- Loader(支持任意模块加载,比如图片、less、css等等)
- 智能解析
- 插件系统
- 快速运行
Vue开发技巧
1、转发 请求
config — index.js — module.exports — dev — proxyTable
proxyTable: {
'/api':{
target:'http://0.0.0.0:8080',
pathRewrite: {
'^/api':'/static/mock'
}
}
},
2、设置路径别名
build — webpack.base.conf.js
module.exports — resolve –a>lias
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'styles': resolve('src/assets/styles'), // 自己配置
在main.js直接 styles,其他地方需要加波浪线 ‘ ~ ’
3、打包上层目录要求
config/index.js/build
–assetsPublicPath: ‘/’, //运行在 根 目录下
assetsPublicPath: ‘/projects’, //运行在projects目录下
4、.vue文件在webstorm中es6语法报错解决方法
1 语法支持es6设置 -- 第一张图
Languages & Frameworks > JavaScript
把 Javascript Language version 改为 ECMAScript 6,这样做所有的.js文件中es6不再报错,但是在.vue文件中es6语法依然报错。
2.vue文件中es6语法报错
(1).打开 Editor => File Types 找到 HTML 添加 *.vue -- (编辑css、js语法提示。存疑)。
(2).粗暴:直接在<script>标签中添加type="text/ecmascript-6",.vue里面的代码会高亮并支持ES6。--好像不推荐
(3).将script标签添加 type=”es6” 属性 --- 第二张图
<script type="es6"></script>
然后打开 Editor => Language Injections 添加 XML Tag Injection,内容如下图。
3.补充新功能:右键新建时出现.vue文件类型,就像新建html文件一样 -- 第三张图
Setting-Editor-File and Code Templates 点击右上角的加号 添加文件 Name为vue File, Extension 为vue,下面的位置可以填写自定义的初始化模板内容。