回顾
基础总结1里简单介绍了什么是vue,为什么使用vue,mvvm设计模式,数据绑定,属性绑定,方法绑定,计算属性,侦听器
计算属性和侦听器区别
1,同步处理运算,计算属性更加方便 2,异步处理侦听器方便
- computed,watch 都是watcher的实例,只是传入的构建参数不同,在vm._watcher可以看到这些实例
- 计算属性同样使用object.defineProperty方法将属性绑定到vue实例上
?这边之后可以详细展开~
样式绑定
有一个常用的结合三目运算tab切换样式
<a :class="active == index?active :''">{{index}}</a>
- 动态 :class 接受一个对象,或表达式
- 静态 class="style"
条件渲染
v-if,v-else
什么是条件渲染:通过v-if指令来判断是否参与到dom渲染
<div id="app">
<p v-if="isShow">v-if</p>
</div>
<script>
new Vue({
el: '#app',
data: {
isShow: true
}
})
</script>
<input v-if="isShow" type="text" placeholder="true" />
<input v-else type="text" placeholder="false" />
上面的例子修改isShow后,value值不会改变
需要加上key,vue可以监听到相应input
<input v-if="isShow" type="text" placeholder="true" key="true" />
<input v-else type="text" placeholder="false" key="false"/>
v-show
v-show 是通过改变display样式来决定是否隐藏的
- v-if是通过动态增删DOM来隐藏显示的
- v-if动态修改DOM,消耗大,用于初始化
- v-if和v-show最大区别在于是否增删DOM,后者只是控制display样式
- 当v-if="true"时,vue会编译为虚拟DOM并缓存,带下次条件渲染直接使用
列表渲染
v-for
v-for 可遍历两种数据类型:数组和对象
v-for="(item, index) in array" v-for="(value, key, index) in object"
<div id="app">
<template v-for="(item, index) in books">
<p>{{ item.id }}</p>
<p>{{ item.name }}</p>
</template>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
books: [
{
id: 1,
name: 'JavaScript'
},
{
id: 2,
name: 'Java'
},
{
id: 3,
name: 'Python'
}]
}
})
</script>
- v-for 可以遍历数组,对象
- 同一元素v-for优先级大于v-if,即先执行遍历,在执行判断
- key值的作用要了解Vue更新DOM机制(后面写),即Diff算法。
- 该算法有三个假设,其中一个是同级元素可以通过唯一id值区分,而key值的作用即作为这个id值,使更新(包括插入,删除,新增,交换等等)时,vue能够甄别到底是哪些虚拟DOM发生了变化,而不是笼统的批量更新。
列表更新(排序,过滤)
理解点: 数组常用方法
arr.sort() : 排序
// 控制台输出
vm.array.sort(function (a, b) {
return a.price - b.price
})
arr.filter(): 过滤
vm.array.filter(function(value){
return value.name.indexOf('xxx')
})
- sort和filter最大区别,sort应用的是同一对象,filter复制了了一个新的数组,Vue感知不到,这里涉及到了变异方法
- vue劫持了sort,做了封装,而filter却没有
- Vue变异方法对原有数组方法进行封装,可以触发Vue更新
Vue变异方法有哪些?
push, pop, unshift, shitf, splice, reverse, sort
Vue数组没有封装的方法 filter,concat,slice,arr[i] = 'xxx'
如何解决没有封装方法执行响应呢?
第一种方法
vm.array = vm.array.filter(function(value){
return value.name.indexOf('xxx')
})
第二种方法 vm.$set 可以动态响应属性
vm.$set(vm.list, index, value)
事件及表单
事件
事件:响应用户输入,返回指令输出
v-on指令,简写"@"
题目:使用v-on写一个加减器
事件修饰符 修饰符:用于部分改变事件逻辑,比如说阻止冒泡了,阻止浏览器默认行为等
- .stop: 阻止事件冒泡
- .self: 当触发事件的对象是自己本身才执行(@click.self="function")(添加.self后,只要event.target为绑定元素自身时执行回调函数)
事件修饰符 二
-
.capture: 监听器采用事件捕获模型 outer,inner 执行顺序:1,outer,inner
-
.once: 监听器触发一次后移除:点击一次监听器被清除
-
.passive:告诉浏览器该监听器是”主动的“.passive效果作用:是为了滑动更顺畅
这三个修饰符用的同一个方法

......
数据双向绑定 v-model
过程:修改视图层数据,DOM listening 修改model数据
v-model 本质是一个语法糖
<input type="text" v-model="text">
<span>{{text}}</span>
<script>
new Vue({
el: '#app',
data: {
text: ''
}
})
</script>
不用v-model如何实现数据双向绑定呢?
这里会用到 @input 监听input事件 oninput
<div id="app">
<input type="text" name="test" :value="text" @input="handlerInput" />
<span>{{text}}</span>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
text: 'test'
},
methods: {
handlerInput: function (event) {
this.text = event.target.value
}
}
})
</script>
总结: v-model 仅仅是语法糖,实际动态绑定value属性,监听input事件,v-model 底层实现是通过模板编译的
v-model修饰符
- .trim : 去除字符串前后的空格
- .number : 将输入的转换为数字类型
- .lazy: v-model.lazy="text"使用lazy修饰符后,修改不会马上改变,失去焦点后执行改变
file 文件上传空间
用到 onchange
<input type="file" @change="handlerFile">
<script>
new Vue({
el: '#app',
data: {
file: null,
},
methods: {
handlerFile: function (evt) {
this.file = evt.target.files[0]
}
}
})
</script>
组件
什么是组件? 是一个功能块的集合,vue本身是由一个组件树组成的,header,content,footer都可以是一个组件。
为什么使用组件? 低耦合,便于维护,一处开发多处使用
组件注册
全局注册,局部注册
注意命名方式: 1,my-name 2,MyName
全局注册:
Vue.component('name', {
template: '',
data: () {
return {
}
}
})
局部注册:
new Vue({
el: '#app',
compontents: {
'my-name': {
template: '',
data () {
return {
}
}
}
}
})
父子组件间传参

props 传参
props用于父组件传参到子组件
<div id="app">
<my-button :count="count"></my-button>
</div>
<!-- <script type="text/javascript" src="js/button.js"></script> -->
<script>
new Vue({
el: '#app',
data: {
count: 10
},
components: {
'my-button': {
data () {
return {}
},
props: {
count: {
type: Number,
default: 1,
validator: function(value) {
return value > 1 && value < 10
}
}
},
template: '<button>{{count}}</button>'
}
}
})
</script>
注意:
注意props 参数 type(类型),default(默认值),validator(为数据添加限制)
props: {
arg: {
type: Number,
default: 1,
validator: function (value) {
return value > 10 && value < 1
}
}
}
自定义事件
// 子组件
this.$emit(functionName, arg1, arg2)
// 父组件
<my-header @funcitonName="ParentFunctionName"></my-header>
methods : {
ParentFunctionName: function (arg1, arg2) {
// arg1, arg2
}
}
- this.$parent : 获取父组件
- this.$children : 子组件数组
兄弟组件传参
file:///Users/xqls/Desktop/笔记/img/borther.png

这里用到 中间件: eventBus.js
var eventBus = new Vue()
vue.prototype.eventBus = eventBus
// child1
this.eventBus.$emit('send', arg)
// child2
created: () {
var that = this
this.eventBus.$on('send', function (text) {
that.text = text
})
}
注意:
- eventBus 是vue的一个实例,this.eventBus.emit('send', arg) , $on分发给另一组件
- created中that = this 是作用域问题,可以看js高程函数表达式那章节
- vuex是状态管理器,可以实现组件间传值
- props中定义的属性是只读的,如果修改vue会抛出错误。
插槽
什么是插槽? 组件内预留位置,在引用组件时插入元素块
官方解释: Vue 实现了一套内容分发的 API,这套 API 基于当前的 Web Components 规范草案,将 元素作为承载分发内容的出口。
语法?
<slot></slot>
// 具名插槽
<slot name="slotName"></slot>
实现一个例子?
<!-- 引用组件,插入内容 -->
<my-content>
<p v-slot="header">my-header</p>
<p v-slot="footer">my-footer</p>
</my-content>
<!-- 子组件模板 -->
<template id="content">
<div>
<slot name="header"></slot>
</div>
<div>
<slot name="footer"></slot>
</div>
</template>
// script 注册子组件
components: {
'my-content': {
template: '#content'
}
}
自定义指令
自定义指令提供一种机制将数据的变化映射为 DOM 行为。
v-if, v-show, v-for, v-model, v-on, b-bind
- 指令组成:v-指令名称:参数.修饰符 = 表达式
- 指令注册:全局注册,局部注册
- 指令都有生命周期,钩子函数
创建一个指令
Vue.directive('test', function(el, bindings, vnode))