1、对于Vue是一套渐进式框架的理解

渐进式代表的含义是:没有多做职责之外的事,vue.js只提供了vue-cli生态中最核心的组件系统和双向
数据绑定,就好像 vuex、vue-router都属于围绕vue.js开发的库。
示例:

使用Angular,必须接受以下东西:

1)必须使用它的模块机制。
2)必须使用它的依赖注入。
3)必须使用它的特殊形式定义组件(这一点每个视图框架都有,这是难以避免的)
所以Angular是带有比较强的排它性的,如果你的应用不是从头开始,而是要不断考虑是否跟其他东西
集成,这些主张会带来一些困扰。

使用React,你必须理解:

1)函数式编程的理念。
2)需要知道它的副作用。
3)什么是纯函数。
4)如何隔离、避免副作用。
5)它的侵入性看似没有Angular那么强,主要因为它是属于软性侵入的。

Vue与React、Angular的不同是,但它是渐进的:

1)可以在原有的大系统的上面,把一两个组件改用它实现,就是当成jQuery来使用。
2)可以整个用它全家桶开发,当Angular来使用。
3)可以用它的视图,搭配你自己设计的整个下层使用。
4)可以在底层数据逻辑的地方用OO和设计模式的那套理念。
5)可以函数式,它只是个轻量视图而已,只做了最核心的东西。

2、vue.js的两个核心是什么?

数据驱动和组件系统:
数据驱动:ViewModel,保证数据和视图的一致性。
组件系统:应用类UI可以看作全部是由组件树构成的。

3、 v-if 和 v-show 有什么区别

相同点
两者都是在判断DOM节点是否要显示。
不同点
(1) 实现方式: v-if是根据后面数据的真假值判断直接从Dom树上删除或重建元素节点。 v-show只是在
修改元素的css样式,也就是display的属性值,元素始终在Dom树上。
(2) 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子
组件; v-show只是简单的基于css切换;
(3) 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局
部编译; v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素始终被
保留;
(4) 性能消耗:v-if有更高的切换消耗,不适合做频繁的切换; v-show有更高的初始渲染消耗,适合做频
繁的额切换;

4、vue常用的修饰符

a、按键修饰符

如:.delete(捕获“删除”和”退格“键) 用法上和事件修饰符一样,挂载在v-on:后面,
语法:

1
<input class='aaa' v-model="inputValue" @keyup.delete="onKey"/>
b、系统修饰符

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器
(1) .ctrl
(2) .alt
(3) .shift
(4) .meta

c、鼠标按钮修饰符

(1) .left
(2) .right
(3) .middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
如: 鼠标滚轮单击触发

1
<button @click.middle ="onClick">

Click默认是鼠标左键单击

d、其他修饰符

(1) .lazy
在默认情况下, v-model 在每次 input 事件触发后将输入框的值与数据进行同步 ,我们可以添
加 lazy 修饰符,从而转变为使用 change 事件进行同步:

1
<input v-model.lazy="msg" >

(2) .number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 .number 修饰符:

1
<input v-model.number="age" type="number">

这通常很有用,因为即使在 type=”number” 时,HTML 输入元素的值也总会返回字符串。如果这个值
无法被 parseFloat() 解析,则会返回原始的值。
(3) .trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

1
<input v-model.trim="msg">

同样前面都有空格加上.trim后 将前后空格都去掉了。

5、v-on可以监听多个方法

v-on可以监听多个方法

1
2
3
4
5
6
<!-- v-on在vue2.x中测试,以下两种均可-->
<button v-on="{mouseenter: onEnter,mouseleave: onLeave}">鼠标进来1</button>
<button @mouseenter="onEnter" @mouseleave="onLeave">鼠标进来2</button>
<!-- 一个事件绑定多个函数,按顺序执行,这里分隔函数可以用逗号也可以用分号-->
<button @click="a(),b()">点我ab</button>
<button @click="one()">点我onetwothree</button>

6、vue中 key 值的作用

使用key来给每个节点做一个唯一标识
key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使
用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效
果。

7、vue-cli工程升级vue版本

npm install -g @vue/cli

8、vue事件中如何使用event对象?

注意在事件中要使用 $ 符号

1
2
3
4
5
6
7
8
9
10
11
//html部分
<a href="javascript:void(0);" data-id="12" @click="showEvent($event)">event</a>
//js部分
showEvent(event){
//获取自定义data-id
console.log(event.target.dataset.id)
//阻止事件冒泡
event.stopPropagation();
//阻止默认
event.preventDefault()
}

9、$nextTick的使用

参数: {Function} [callback]

用法:将回调延迟到下次DOM更新循环之后执行。在修改数据之后立即使用它,然后等待DOM更新。
它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

理解nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数,

实例:

未使用this.$nextTick()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<p ref="msgp">{{msg}}</p>
<button @click="change">$nextTick</button>
</div></template>
<script>export default {
name: 'nextTick',
data() {
return {
msg: '未更新'
}
},
methods: {
change() {
// 修改数据
this.msg = '被更新了'
// DOM还没有更新
console.log(this.$refs.msgp.innerHTML)
this.$nextTick(() => {
// DOM更新了
console.log('$nextTick:' + this.$refs.msgp.innerHTML)
})
}
},
created() {
}
}
</script>

使用this.$nextTick()

1
2
3
4
5
6
7
8
9
10
methods:{    
testClick:function(){
let that=this;
that.testMsg="修改后的值";
that.$nextTick(function(){
console.log(that.$refs.aa.innerText); /
/输出:修改后的值
});
}
}

注意:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM。

$nextTick() 的应用场景:

在vue的生命周期 created() 钩子函数中进行 dom 操作,一定要放在 $nextTick() 函数中执行。在created() 钩子函数执行的时候 DOM 其实并未进行任何渲染,而此时进行 DOM 操作无异于徒劳,所以此处一定要将 DOM 操作的代码放进 nextTick() 的回调函数中。

mounted() 钩子函数,因为该钩子函数执行时,所有的 DOM 挂载和 渲染都已完成,此时在该钩子函数中进行任何 DOM 操作都不会有问题,

数据变化后要执行某个操作,而这个操作需要随数据改变而改变DOM结构时,这个操作都是需要放置$nextTick() 的回调函数中。

10、Vue 组件中 data 为什么必须是函数

在 new Vue() 中, data 是可以作为一个对象进行操作的,然而在 component 中, data 只能以函数的形式存在,不能直接将对象赋值给它。

当data选项是一个函数的时候,每个实例可以维护一份被返回对象的独立的拷贝,这样各个实例中的
data不会相互影响,是独立的。

11、v-for 与 v-if 的优先级

当它们处于同一节点,v-for的优先级比v-if更高,这意味着 v-if将分别重复运行于每个 v-for循环中。当你想为仅有的一些项渲染节点时,这种优先级的机制会十分有用,如下:

1
2
3
<li v-for="todo in todos" v-if="!todo.isComplete">	
{{ todo }}
</li>

上面的代码只传递了未完成的 todos。

而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template> )上。如:

1
2
3
4
5
6
<ul v-if="!todo.isComplete">	
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>

12、vue中子组件调用父组件的方法

第一种方法

直接在子组件中通过this.$parent.event来调用父组件的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//父组件
<template>
<div>
<child></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
//子组件
<template>
<div>
<button @click="childMethod()">点击</button>
</div></template><script>export default {
methods: {
childMethod() {
this.$parent.fatherMethod();
}
}
};
</script>
第二种方法

在子组件里用 $emit 向父组件触发一个事件,父组件监听这个事件就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//父组件
<template>
<div>
<child @fatherMethod="fatherMethod"></child>
</div></template><script>import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//子组件
<template>
<div>
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
methods: {
childMethod() {
this.$emit('fatherMethod');
}
}
};
</script>
第三种方法

父组件把方法传入子组件中,在子组件里直接调用这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//父组件
<template>
<div>
<child :fatherMethod="fatherMethod"></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//子组件
<template>
<div>
<button @click="childMethod()">点击</button>
</div></template><script>
export default {
props: {
fatherMethod: {
type: Function,
default: null
}
},
methods: {
childMethod() {
if(this.fatherMethod){
this.fatherMethod();
}
}
}
};
</script>

13、vue中 keep-alive 组件的作用

作用:用于保留组件状态或避免重新渲染(缓存的作用)
例子:当一个目录页面与一个详情页面,用户经常:打开目录页面**=>进入详情页面=>返回目录页面=>**打开详情页面,这样目录页面就是一个使用频率很高的页面,那么就可以对目录组件使用 <keep-alive></keep-alive> 进行缓存,这样用户每次返回目录时,都能从缓存中快速渲染,而不用重新渲染。

14、vue中如何编写可复用的组件?

组件定义:是一个具有一定功能,且不同组件间功能相对独立的模块。高内聚、低耦合。

开发可复用性的组件应遵循以下原则

1)规范化命名:组件的命名应该跟业务无关,而是依据组件的功能命名。
2)数据扁平化:定义组件接口时,尽量不要将整个对象作为一个 prop 传进来。每个 prop 应该是一个简单类型的数据。这样做有下列几点好处:
(1) 组件接口清晰。
(2) props 校验方便。
(3) 当服务端返回的对象中的 key 名称与组件接口不一样时,不需要重新构造一个对象。扁平化的 props 能让我们更直观地理解组件的接口。

1
2
3
<!-- 反例 -->
<card :item="{ title: item.name, description: item.desc, poster: item.img }>
</card>
1
2
3
<!-- 正例 -->
<card :title="item.name" :description="item.desc" :poster="item.img">
</card>

3)可复用组件只实现 UI 相关的功能,即展示、交互、动画,如何获取数据跟它无关,因此不要在组件
内部去获取数据。
4)可复用组件应尽量减少对外部条件的依赖,所有与 vuex 相关的操作都不应在可复用组件中出现。
5)组件在功能独立的前提下应该尽量简单,越简单的组件可复用性越强。
6)组件应具有一定的容错性。
7)组件应当避免对其父组件的依赖,不要通过 this.parent 来操作父组件的示例。父组件也不要通过
this.children 来引用子组件的示例,而是通过子组件的接口与之交互。
8)可复用组件除了定义一个清晰的公开接口外,还需要有命名空间。命名空间可以避免与浏览器保留标签和其他组件的冲突。特别是当项目引用外部 UI 组件或组件迁移到其他项目时,命名空间可以避免很多命名冲突的问题。

15、什么是vue生命周期?

定义

vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行
的,在生命周期的不同阶段调用对应的钩子函数实现组件数据管理和DOM渲染两大重要功能。

img

八个阶段:

1)创建前(beforeCreate)
对应的钩子函数为beforeCreate。此阶段为实例初始化之后,此时的数据观察和事件机制都未形
成,不能获得DOM节点。

2)创建后(created)
对应的钩子函数为created。在这个阶段vue实例已经创建,仍然不能获取DOM元素。

3,载入前(beforeMount)
对应的钩子函数是beforeMount,在这一阶段,我们虽然依然得不到具体的DOM元素,但vue挂
载的根节点已经创建,下面vue对DOM的操作将围绕这个根元素继续进行;beforeMount这个阶
段是过渡性的,一般一个项目只能用到一两次。

4,载入后(mounted)
对应的钩子函数是mounted。mounted是平时我们使用最多的函数了,一般我们的异步请求都写
在这里。在这个阶段,数据和DOM都已被渲染出来。

5,更新前(beforeUpdate)
对应的钩子函数是beforeUpdate。在这一阶段,vue遵循数据驱动DOM的原则。beforeUpdate
函数在数据更新后虽然没立即更新数据,但是DOM中的数据会改变,这是Vue双向数据绑定的作用。

6,更新后(updated)
对应的钩子函数是updated。在这一阶段DOM会和更改过的内容同步。

7,销毁前(beforeDestroy)
对应的钩子函数是beforeDestroy。在上一阶段Vue已经成功的通过数据驱动DOM更新,当我们不
再需要vue操纵DOM时,就要销毁Vue,也就是清除vue实例与DOM的关联,调用destroy方法可以
销毁当前组件。在销毁前,会触发beforeDestroy钩子函数。

8,销毁后(destroyed)对应的钩子函数是destroyed。
在销毁后,会触发destroyed钩子函数。
vue生命周期的思想贯穿在组件开发的始终,通过熟悉其生命周期调用不同的钩子函数,我们可
以准确的控制数据流和其对DOM的影响;vue生命周期的思想是Vnode和MVVM的生动体现和继承。

16、vue生命周期钩子函数有哪些?

1)vue生命周期是vue实例化或者组件创建到消亡的过程。
2)beforeCreate 创建前的状态,初始化事件和生命周期。
3)创建完毕状态Init (初始化) injections (依赖注入) & reactivity (开始响应)。
4)beforeMount 挂载前状态, 是否有元素el,是否有模板,是否渲染到了函数内,是否作为模板进行了outerHTML渲染到了页 面,向虚拟DOM上挂载的过程,并且还是把我们的‘#app’生成虚拟DOM,生成完毕后并渲染到view层。
5)mounted 挂载结束状态,渲染到真正的DOM。
6)beforeUpdate可以拿到Vue实例化改变前的状态。
7)Updated拿到变动完成的状态。
8)beforeDestroy消亡前的状态。
9)destroyed实例化或组件被摧毁消亡。

17、vue如何监听键盘事件中的按键?

在Vue中,已经为常用的按键设置了别名,这样我们就无需再去匹配 keyCode ,直接使用别名就能监听按键的事件。例如:

1
<input @keyup.enter="function">

对应表如下:

别名 实际键值
.delete delete(删除)/BackSpace(退格)
.tab Tab
.enter Enter(回车)
esc Esc(退出)
.space Space(空格键)
.left Left(左箭头)
.up Up(上箭头)
.right Right(右箭头)
.down Down(下箭头)
.ctrl Ctrl
.alt Alt
.shift Shift
.meta (window系统下是window键,mac下是command键)

另外,Vue中还支持组合写法

组合写法 按键组合
@keyup.alt.67=”function” Alt + C
@click.ctrl=”function” Ctrl + Click

但是,如果是在自己封装的组件或者是使用一些第三方的UI库时,会发现并不起效果,这时就需要用到 .native 修饰符了,如:(使用Element-UI)

1
2
3
<el-input	
v-model="inputName" placeholder="搜索你的文件" @keyup.enter.native="searchFile(params)">
</el-input>

如果遇到 .native 修饰符也无效的情况,可能就需要用到 $listeners 了.

  • 18、vue更新数组时触发视图更新的方法

    1)Vue.set 响应式新增与修改数据

    可以设置对象或数组的值,通过key或数组索引,可以触发视图更新

    ​ Vue.set(target,key,value)

    • 参数:

      • {object | Array} target

      • { string | number} key

      • {any} value

    • 返回值:设置的值

    • 用法:设置对象的属性,如果对象是响应式的,确保属性被创建后也是响应式的,同时出发视图更新。这个方法主要用于避开Vue不能检测属性被添加的限制。

      对象不能是Vue实例,或者Vue实例的根数据对象。

      target:要更改的数据源(可以是对象或者数组)
      key:要更改的具体数据
      value :重新赋的值

    例子:

    1
    2
    //数组修改
    Vue.set(array, indexOfItem, newValue)this.array.$set(indexOfItem, newValue)
    1
    2
    //对象修改
    Vue.set(obj, keyOfItem, newValue)this.obj.$set(keyOfItem, newValue)
    2)Vue.delete(target,key)
    • 删除对象或数组中元素,通过key或数组索引,可以触发视图更新

    • 用法:删除对象的属性。如果对象是响应式的,确保删除能出发更新视图。这个方法主要用于避开Vue不能检测到属性被删除的限制。(至少会用)

      对象不能是Vue实例,或者Vue实例的根数据对象。

    例子:

    1
    2
    //数组修改
    Vue.delete(array, indexOfItem)this.array.$delete(indexOfItem)
    1
    2
    //对象修改
    Vue.delete(obj, keyOfItem)this.obj.$delete(keyOfItem)
    3)数组对象直接修改属性,可以触发视图更新
    1
    2
    3
    4
    this.array[0].show = true;
    this.array.forEach(function(item){
    item.show = true;
    });
    4)splice方法修改数组,可以触发视图更新
    1
    this.array.splice(indexOfItem, 1, newElement)
    5)数组整体修改,可以触发视图更新
    1
    2
    3
    var tempArray = this.array;
    tempArray[0].show = true;
    this.array = tempArray;
    6)用Object.assign或lodash.assign可以为对象添加响应式属性,可以触发视图更新
    1
    2
    3
    4
    5
    6
    //Object.assign的单层的覆盖前面的属性,不会递归的合并属性
    this.obj = Object.assign({},this.obj,{a:1, b:2})
    //assign与Object.assign一样
    this.obj = _.assign({},this.obj,{a:1, b:2})
    //merge会递归的合并属性
    this.obj = _.merge({},this.obj,{a:1, b:2})
    7) Vue包含一组观察数组变异的方法,使用它们改变数组也会触发视图更新
    • push() =>向数组的末尾添加一个或多个元素,并返回新的长度。
    • pop() =>删除最后一个元素,把数组长度减 1,并且返回它删除的元素的值。
    • shift() =>把数组的第一个元素从其中删除,并返回第一个元素的值。
    • unshift() =>向数组的开头添加一个或更多元素,并返回新的长度。
    • splice() =>向/从数组中添加/删除项目,然后返回被删除的项目。 该方法会改变原始数组。
    • sort() =>对数组的元素进行排序。
    • reverse() =>颠倒数组中元素的顺序。

    不变异的方法:

    • filter()
    • concat()
    • slice()
      他们返回的是一个新数组,使用这些方法时,可以用新数组来替换原始数组
    原理:
    • Vue 在检测到数组变化时,并不是直接重新渲染整个列表,而是最大化复用DOM元素。替换的数组中,含有相同元素的项不会被重新渲染,因此可以大胆的用新数组来替换旧数组,不用担心性能问题。

    • 值得注意的是:
      以下变动的数组中Vue是不能检测到的,也不会触发视图更新
      1.通过索引直接设置项, 比如this.books[3]={…}
      2.修改数组长度, 比如 this.books.length = 1;

      两个问题都可以用splice来解决:
      第一个问题 还可以用 set方法 this.$set(this.books,3,{…})

    19、vue中对象更改检测的注意事项

    还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:

    1
    2
    3
    4
    5
    6
    var qs = new Vue({	
    data: {
    a: 1
    }})
    // `qs.a` 现在是响应式的qs.b = 2
    // `qs.b` 不是响应式的

    对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object,
    propertyName, value) 方法向嵌套对象添加响应式属性。例如,对于:

    1
    2
    3
    4
    5
    6
    7
    var qs = new Vue({	
    data: {
    userProfile: {
    name: 'Jungle'
    }
    }
    })

    你可以添加一个新的 age 属性到嵌套的 userProfile 对象:

    1
    Vue.set(qs.userProfile, 'age', 27)

    你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:

    1
    qs.$set(qs.userProfile, 'age', 27)

    有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新属性不会触发更新,在这种情况下,你应该用两个对象(原对象和要混合进去的对象)的属性创建一个新的对象。所以,如果你想添加新的响应式属性,这样做:

    1
    2
    3
    4
    qs.userProfile = Object.assign({}, qs.userProfile, {	
    age: 27,
    favoriteFood: 'Vue huimian'
    })

    拓展:

    Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。

    const target = { a: 1, b: 2 };
    const source = { b: 4, c: 5 };

    const returnedTarget = Object.assign(target, source);

    console.log(target);
    // expected output: Object { a: 1, b: 4, c: 5 }

    console.log(returnedTarget);
    // expected output: Object { a: 1, b: 4, c: 5 }

    20、解决非工程化项目初始化页面闪动问题

    vue页面在加载的时候闪烁花括号{},v-cloak指令和css规则如[v-cloak]{display:none}一起用时,这个指令可以隐藏未编译的Mustache(前端模板引擎)标签直到实例准备完毕。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [v-cloak] {		
    display: none;
    }
    <!--html代码-->
    <div id="app" v-cloak>
    <ul>
    <li v-for="item in tabs">
    {{data.text}}
    </li>
    </ul>
    </div>

    21、v-for产生的列表,实现active的切换

    1
    2
    3
    4
    5
    6
    7
    8
    <div v-for="(desc,tableIndex) in descriptions.firstface">	
    <ul class="controller-checkboxs clearfix" >
    <li
    @click="currentIndex=index,currentTable=tableIndex" class="controller-checkbox-item"
    :class="{active:index===currentIndex&&tableIndex==currentTable}" v-for="(ctrlValue,index) in desc.args">
    </li>
    </ul>
    </div>

    22、v-model语法糖的组件中的使用

    1
    2
    3
    <input type="text" v-model="msg">
    此时msg值就与input的值进行双向绑定,实际上上面的代码是下面代码的语法糖。
    <input v-bind:value="msg" v-on:input="msg= $event.target.value"/>

    要理解这行代码,首先你要知道 input 元素本身有个 oninput 事件,这是 HTML5 新增加的,类似
    onchange ,每当输入框内容发生变化,就会触发 oninput ,把最新的value传递给 msg。从而实现了vmodel。

    23、Vue中自定义过滤器

    过滤器是一个通过输入数据,能够及时对数据进行处理并返回一个数据结果的简单函数。Vue有很多很
    便利的过滤器,过滤器通常会使用管道标志 “ | ”。使用:

    1
    <td>{{item.ctime | dataFormat('yyyy-mm-dd')}}</td>

    自定义全局过滤器
    虽然VueJs给我们提供了很多强有力的过滤器,但有时候还是不够。值得庆幸的,Vue给我们提供了一个干净简洁的方式来定义我们自己的过滤器,之后我们就可以利用管道 “ | ” 来完成过滤。

    定义一个全局的自定义过滤器,需要使用 Vue.filter() 构造器。这个构造器需要两个参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 定义一个全局过滤器
    Vue.filter('dataFormat', function (input, pattern = '') {
    var dt = new Date(input);
    // 获取年月日
    var y = dt.getFullYear();
    var m = (dt.getMonth() + 1).toString().padStart(2, '0');
    var d = dt.getDate().toString().padStart(2, '0');
    // 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日
    // 否则,就返回 年-月-日 时:分:秒
    if (pattern.toLowerCase() === 'yyyy-mm-dd') {
    return `${y}-${m}-${d}`;
    } else {
    // 获取时分秒
    var hh = dt.getHours().toString().padStart(2, '0');
    var mm = dt.getMinutes().toString().padStart(2, '0');
    var ss = dt.getSeconds().toString().padStart(2, '0');
    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
    }
    });

    拓展

    padStart() 方法用另一个字符串填充当前字符串(如果需要的话,会重复多次),以便产生的字符串达到给定的长度。从当前字符串的左侧开始填充。

    1
    2
    3
    4
    5
    'abc'.padStart(10);          //"       abc"
    'abc'.padStart(10, "foo"); // "foofoofabc"
    'abc'.padStart(6,"123465"); // "123abc"
    'abc'.padStart(8, "0"); // "00000abc"
    'abc'.padStart(1); // "abc"

    返回值:在原字符串开头填充指定的填充字符串直到目标长度所形成的新字符串。

    24、vue等单页面应用及其优缺点

    优点:

    1)用户体验好,快,内容的改变不需要重新加载整个页面,对服务器压力较小。
    2)前后端分离,比如vue项目
    3)完全的前端组件化,前端开发不再以页面为单位,更多地采用组件化的思想,代码结构和组织方
    式更加规范化,便于修改 和调整;

    缺点:

    1)首次加载页面的时候需要加载大量的静态资源,这个加载时间相对比较长。
    2)不利于 SEO优化,单页页面,数据在前端渲染,就意味着没有 SEO。
    3)页面导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进
    后退功能,所以需要自 己建立堆栈管理)

    25、什么是vue的计算属性?

    模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板
    过重且难以维护。

    1
    2
    3
    4
    //翻转字符串
    <div id="example">
    {{ message.split('').reverse().join('') }}
    </div>

    这里的表达式包含3个操作,并不是很清晰,所以遇到复杂逻辑时应该使用Vue特带的计算属性
    computed 来进行处理。

    26、vue-cli提供的几种脚手架模板

    vue-cli 的脚手架项目模板有browserify 和 webpack , 官网给出了两个模板: webpack-simple 和
    webpack 两种。两种的区别在于webpack-simple 没有包括Eslint 检查功能等等功能,普通项目基本用
    webpack-simple 就足够了.
    搭建官方项目模板步骤:

    • 1、npm install vue-cli (安装vue-cli ) 有的时候有看到其它两种写法: –save-dev 和 –save的写法。这两个有一定的区别,我们都知道package.json 中有一个 “dependencies” 和 “devDependencies” 的。
      dependencies 是用在开发完上线模式的,就是有些东西你上线以后还需要依赖的,比如juqery , 我们这里的vue 和 babel-runtime(Babel 转码器 可以将ES6 转为ES5 ), 而devDependencies 则是在开发模式执行的,比如我们如果需要安装一个node-sass 等等。

      • 有的时候看到package.json中安装的模块版本号前面有一个波浪线。

      例如: ~1.2.3 这里表示安装1.2.x以上版本。但是不安装1.3以上。

      • 插入符号^ 更宽松。 它匹配的是最新次要版本号,也就是第二个数字。

      比如:^ 1.2.3将匹配任何1.x.x版本,包括1.3.0,但将在2.0.0上停止。

    • 2、vue init webpack-simple yourdemoname 下载一个webpack-simple项目,这里的webpacksimple 是固定的,也就是官网的项目模板。youdemoname 这个是你自己项目的名字。 执行这个步骤
      以后。就会弹出询问 “项目名称..项目描述“等等问题 直接按照提示操作。这个时候对应的项目目录下就
      出现刚刚建立的项目了。

    • 3、我们还需要把项目的依赖下载下来。使用命令: cd youdemoname 然后执行npm install 就可以了,
      这个时候你的项目中有多了一个node_modules 目录

    • 4、使用”npm - run - dev” 命令来运行项目 “npm-run-bulid” 来执行发布,会自动生成dist文件

    27、vue父组件如何向子组件中传递数据?

    • 子组件在props中创建一个属性,用以接收父组件传过来的值(也可以是对象)

    • 父组件中注册子组件,并在<template>中添加child标签,标签中添加message属性并赋值

    • 在子组件标签中添加子组件props中创建的属性

    • 把需要传给子组件的值赋给该属性

    28、计算属性的缓存和方法调用的区别

    • 计算属性必须返回结果

    • 计算属性是基于它的依赖缓存的。一个计算属性所依赖的数据发生变化时,它才会重新取值。

    • 使用计算属性还是methods取决于是否需要缓存,当遍历大数组和做大量计算时,应当使用计算属
      性,除非你不希望得到缓存。

    • 计算属性是根据依赖自动执行的,methods需要事件调用

    29、vue-cli中自定义指令的使用

    • vue中除了内置的指令(v-show,v-model)还允许我们自定义指令
    • 想要创建自定义指令,就要注册指令(以输入框获取焦点为例) 注意:autofocus 在移动版 Safari 上不工作
    一、注册全局指令:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 注册一个全局自定义指令 `v-focus`
    Vue.directive('focus', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted: function (el,binding) {
    // 当前指令绑定的dom元素
    //console.log(el);
    // 指令传入的参数、修饰符、值 v-指令名称:参数.修饰符=值
    // console.log(binding)
    // 聚焦元素
    el.focus()
    }
    })
    二、注册局部指令: 组件中也接受一个 directives 的选项
    1
    2
    3
    4
    5
    6
    7
    8
    directives: {
    focus: {
    // 指令的定义
    inserted: function (el) {
    el.focus()
    }
    }
    }

    使用也很简单:直接在元素上面使用v-focus即可:

    1
    <input type="text" v-focus/>
    三、举一个自定义指令的小例子:拖拽
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    Vue.directive('drag', {
    // 当指令绑定到元素上的时候执行
    bind(el, binding) {
    // console.log('bind');
    // 当前指令绑定的dom元素
    //console.log(el);
    // 指令传入的参数、修饰符、值 v-指令名称:参数.修饰符=值
    // console.log(binding)
    el.onmousedown = function(e) {
    var e = e||event;
    let disX = e.clientX - el.offsetLeft;
    let disY = e.clientY - el.offsetTop;

    document.onmousemove = function(e) {
    var e = e||event;
    let L = e.clientX - disX;
    let T = e.clientY - disY;
    if (binding.modifiers.limit) {
    if (L < 0) {
    L = 0;
    }
    }
    el.style.left = L + 'px';
    el.style.top = T + 'px';
    };
    document.onmouseup = function() {
    document.onmousemove = null;
    };

    return false;
    }
    }
    });

    使用也很简单,只用在元素上添加v-drag或者v-drag.limit

    1
    2
    <div id="div1" v-drag.limit></div>
    <div id="div2" v-drag></div>