MVVM
M层:数据
V层:模版标签
VM层:对数据进行操作,由Vue来实现(虚拟DOM)
Vue指令
v-bind 元素节点和 Vue 实例的属性保持一致
v-on 添加一个事件监听器
v-if
v-show
<!--v-show的实际效果-->
<div style="display: none;">hahahahaha</div>
v-for
v-model 轻松实现表单输入和应用状态之间的双向绑定
除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法,它们都有前缀 $
生命周期钩子
每个 Vue 实例在被创建时都要经过一系列的初始化过程,在这个过程中也会运行一些叫做生命周期钩子的函数
模板语法
插值
1.文本: {{ }}
2.原始HTML: v-html
3.修饰符 (Modifiers) :以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()(阻止元素发生默认的行为)
缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
计算属性
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
计算属性缓存 vs 方法
<p>Reversed message: "{{ reversedMessage() }}"</p>
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
可以通过在表达式中调用方法来达到同样的效果,不同的是计算属性是基于它们的依赖进行缓存的,只在相关依赖发生改变时它们才会重新求值。
计算属性缓存 vs 侦听属性
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性,但是需要对每一个变动的数据都进行侦听,比计算属性麻烦的多。
计算属性的setter
计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :
computed: {
fullName: {
get: function () {
return this.firstName + ' ' + this.lastName
},
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
运行 vm.fullName = ‘John Doe’ 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新。
Class 与 Style 绑定
绑定Class
1.对象语法
<div v-bind:class="{ active: isActive }"></div>
data: {
isActive: true
}
<div class="static" v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
结果渲染为:
<div class="static active"></div>
2.数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
绑定内联样式
v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用单引号括起来) 来命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
数组更细检测
不能通过操作数组下边的方式操作数据数据
必须使用vue提供的7个数组的变异方式来操作数组
push() 数组增加一条
pop() 删除数组最后一项
shift() 删除数组第一项
unshift() 往数组第一项加一点内容
splice() 数组截取
sort() 数组排序
reverse() 数组取反
vm.list.splice(1, 1, {id:“333”, text: “Dell1”})从下标1开始,截取1项修改为
也可以通过改变数组的引用地址 vm.list = [{…}]
使用Vue中的set方法
对象:
Vue.set(vm.userInfo, "address", "beijing")
vm.$set(vm.userInfo, "address", "beijing")
数组:
Vue.set(vm.list, 1, {id:"000001", text:"Mike"})
vm.$set(vm.list, 1, {id:"000001", text:"Mike"})
事件处理
事件修饰符
在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
.stop
.prevent
.capture
.self
.once
.passive
按键修饰符
在监听键盘事件时,我们经常需要检查常见的键值。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<input @keyup.enter=“submit”>
全部的按键别名:
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
表单输入绑定
v-model 指令在表单 input、textarea 及 select 元素上创建双向数据绑定
组件传值
tr会和table同级的一层中,因为h5的规范里面table里面必须是tboby,tboby里面必须是tr, 出现这种问题,我们可以使用vue提供的is属性解决问题,这里虽然写的是tr但是表示是显示row的组件, ul ol select
<tr is="row"></tr>
<div id="app">
<counter :count="1" @inc="handleIncrease"></counter>
<counter :count="2" @inc="handleIncrease"></counter>
<div>{{total}}</div>
</div>
<script>
// 单向数据流,props接收父组件传递的数据,但是接收的数据子组件只能使用不能改变
// 因为父组件如果是一个对象(引用数据)时,可能会被其他的子组件引用,如果改变也会影响其他子组件
// 父组件通过属性的形式向子组件传值
// 子组件通过事件触发的形式向父组件传值
var counter = {
props: ['count'],
data: function() {
return {
number: this.count
}
},
template: '<div @click="handleClick">{{number}}</div>',
methods: {
handleClick: function () {
this.number = this.number + 2
this.$emit('inc', 2)
}
}
}
var vm = new Vue({
el: "#app",
data: {
total: 3
},
components: {
counter: counter
},
methods: {
handleIncrease: function (step) {
this.total += step;
}
}
})
</script>
props特性和非props特性
props特性,父组件向子组件传值的时候,子组件恰好声明了这个值,子组件就能将这个值显示出来
非props特性,未声明,子组件无法使用值,且属性会展示在子组件最外层的DOM标签的html属性里面
<child :content="'hello world'"></child>
// child组件中未声明content,则页面显示为:
<div content="'hello world'"></div>
组件绑定原生事件
<div id="app">
<child @click.native="handleClick"></child>
</div>
<script>
// @click.native做事件的监听,监听的并不是自定义事件(内部组件向外触发的自定义事件),而是一个原生的点击事件
Vue.component('child', {
template: '<div> <!--@click="handleChildClick"-->child</div>',
/*methods: {
handleChildClick: function () {
alert('child click');
this.$emit('click')
}
}*/
})
var vm = new Vue({
el: "#app",
methods: {
handleClick: function () {
alert('click')
}
}
})
</script>
插槽
<div id="app">
<child content='<p>Dell</p>'></child>
<child1>
<p>Dell</p>
</child1>
<body-content>
<div class="header" slot="header">header</div>
<div class="footer" slot="footer">footer</div>
</body-content>
</div>
<script>
// 子组件有一部分内容是根据父组件传递过来的DOM进行显示时候
// 普通传值问题
// 1.v-html无法使用template模版占位符,只能使用div包裹
// 2.如果代码过多,会很难去阅读
Vue.component('child', {
props: ['content'],
template: `<div>
<p>hello</p>
<div v-html="this.content"></div>
</div>`
})
// 使用插槽
Vue.component('child1', {
template: `<div>
<p>hello</p>
<slot>默认内容</slot>
</div>`
})
// 具名插槽
Vue.component('body-content', {
template: `<div>
<slot name="header1">
<h1>default header</h1>
</slot>
<slot name="header"></slot>
<div class="content">content</div>
<slot name="footer"></slot>
</div>`
})
var vm = new Vue({
el: "#app"
})
</script>
作用域插槽
带有一个可从子组件获取数据的可复用的插槽
<div id="app">
<child>
<template slot-scope="props">
<li>{{props.item}} - hello</li>
</template>
</child>
</div>
<script>
// 作用域插槽,必须template,在 2.5.0+,slot-scope 不再限制在 <template> 元素上使用
Vue.component('child', {
data: function (){
return {
list: [1,2,3,4]
}
},
template: `<div>
<ul>
<slot v-for="item of list" :item=item>
</slot>
</ul>
</div>`
})
var vm = new Vue({
el: "#app"
})
</script>