一、 简单介绍
二、安装和部署
1.用cli在命令行搭建脚手架
2.直接引用vue.js
3.引入cdn
4.npm安装
三、简单应用
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统。
vue 主要分为视图和脚本。
vm (viewModel)表示vue 实例。
1.数据与方法
当一个vue实例被创建时,它将data对象中的所欲属性加入到vue的响应式系统中。当这些属性的值发生改变时,视图将会响应,匹配更新为新的值。这里唯一的例外是Object.freeze(),会阻止修改现有属性,响应系统无法追踪变化。
watch 会观察变量的变化,能够记录oldVal和newVal。
2.生命周期
生命周期钩子需要在new vue()创建时,以属性方式进行声明,写在vue实例内。注意一点:不能使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos())
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。也就是在页面调用之前的生命周期。
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前尚不可用。
在挂载开始之前被调用:相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用。
挂载成功。实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。 如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.$el也在文档内。
注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
3.模版语法----插值
#文本
Message: {{ msg }}
一旦msg发生变化,页面的值也会随之变化。如果想只插入一次,不会再变,用v-once,比如:
<span v-once></span>
#原始html
<p v-html>{{msg}}</p> 这样msg中的html标签能被识别。
#绑定属性
v-bind 动态绑定某个属性
4.模版语法----指令
指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 是例外情况)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
#缩写
v-bind缩写 :
v-on的缩写 @
#修饰符
<div @click="click1">
<div @click.stop="click2">Click me</div>
</div>
@click.stop中的stop是修饰符,表示等自己的click事件执行完成后,不再执行父级的click事件了。
5.绑定class 和style
当有如下模板 :
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
data 如下:
data: {
isActive: true,
hasError: false}
第一个active: 是属性,isActive 是data 中的属性,active 这个 class 存在与否将取决于数据属性 isActive 的 truthiness。
我们也可以在这里绑定一个返回对象的计算属性。这是一个常用且强大的模式:
HTML
<div v-bind:class="classObject"></div>
JS
data: {
isActive: true,
error: null},computed: {
classObject: function(){
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal' }
}
}
6.条件渲染
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
可以使用 v-else 指令来表示 v-if 的“else 块”。v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用。带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。
v-show是根据条件展示元素。值得注意的是:v-show 不支持 <template> 元素,也不支持 v-else。
v-if vs v-show:
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
7.列表渲染
v-for指令基于一个数组来渲染一个列表。
关于数组:
v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。也可以用item,index in items 的形式,或者(item, index) in items 的形式,参数index代表数组的索引。
数组中也可以用of 代替in,比如:item of items;
关于对象:
同样获取值:value in object
获取值和键名:(value, name) in object
获取值,键名,索引:(value, name, index) in object
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
#数据检测更新
##变异方法
变异方法,会改变调用了这些方法的原始数组。
Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
##替换数组
非变异 (non-mutating method) 方法,例如 filter()、concat() 和 slice() 。它们不会改变原始数组,而总是返回一个新数组。
##注意事项
由于 JavaScript 的限制,Vue 不能检测以下数组的变动(也就是说不是响应式的):
1.当利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
2.当修改数组的长度时,例如:vm.items.length = newLength
但是要实现上面两个情况,也是有方法的,同时也将在响应式系统内触发状态更新:
Vue.set(vm.items, indexOfItem, newValue);
vm.items.splice(newLength)
#对象检测更新
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除。
但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。
还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名。
需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。要像这样:
vm.userProfile = Object.assign({}, vm.userProfile, { age: 27, favoriteColor: 'Vue Green'})
#显示过滤后和排序后的结果
不实际改变或重置原始数据,只显示过滤后和排序后的结果,可以创建一个计算属性,来返回过滤或排序后的数组。
例如:
HTLM
<li v-for="n in evenNumbers">{{ n }}</li>
JS
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function(){
return this.numbers.filter(function(number){
return number % 2 === 0 })
}
}
在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 可以使用methods方法
HTML
<li v-for="n in even(numbers)">{{ n }}</li>
JS
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},methods: {
even: function(numbers){
return numbers.filter(function(number){
return number % 2 === 0 })
}
}
7.事件处理
#监听事件
v-on监听DOM,只限于简单监听,一般事务的逻辑比较复杂,要写在methods 组件中。
#事件修饰符
事件修饰符为了让方法只处理数据逻辑,不处理DOM细节。处理DOM细节交给事件修饰符。常见的有
.stop 阻止事件继续传播
.prevent 阻止页面重载
.capture
.self
.once 只触发一次
.passive
实参 vs 形参
实参 全称为"实际参数"是在调用时传递给函数的参数;形参全称为"形式参数" 由于它不是实际存在变量,所以又称虚拟变量。是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数.在调用函数时,实参将赋值给形参。
8.表单输入绑定
可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
#修饰符
.lazy 使用 change 事件进行同步,
.number 自动将用户的输入值转为数值类型,
.trim 自动过滤用户输入的首尾空白字符。
9.组件基础
可以把经常重复使用的功能封装为组件,v.js用vue.component()函数创建一个组件。与new vue()接受相同的选项。可以使用props 定义组件的属性。
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
每个组件只能有一个根节点,所以在最外层用<div>包起来。这样可以实现在组件内使用多个html标签的效果。当html结构越来越复杂时,可以重构组件,例如:
HTML
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
Js
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`})
#监听子组件
像上面,将组件重构后,它的一些功能可能要求和父级组件(html部分)进行沟通。父级组件可以像处理 native DOM 事件一样通过 v-on 监听子组件实例的事件;同时子组件可以通过调用内建的 $emit 方法 并传入事件名称来触发一个事件。
有的时候用一个事件来抛出一个特定的值是非常有用的。这时可以使用 $emit 的第二个参数来提供这个值:
HTML
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
HTML 增加函数
<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>
那么这个值将会作为第一个参数传入这个方法:
methods: {
onEnlargeText:function(enlargeAmount)
{
this.postFontSize += enlargeAmount
}
}
四、深入了解组件
1.组件注册
用Vue.component 来创建组件,是全局注册。
优点是:全局注册后,可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中
缺点是:全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
局部注册:通过一个普通的 JavaScript 对象来定义组件:
varComponentA = {/* ... */}
varComponentB = {/* ... */}
然后在 components 选项中定义你想要使用的组件:
newVue({el:'#app',
components: {'component-a': ComponentA,'component-b': ComponentB }})
局部注册的组件在其子组件中不可用。
2.模块系统
一般用import/require 使用一个模块系统,比如要使用 Babel 和 webpack 的模块系统,最好
创建一个 components 目录,并将每个组件放置在其各自的文件中。
#模块中局部注册
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'
export default {
components: {
ComponentA,
ComponentC
},
// ...}
#基础组件中自动注册
网友评论