Vue.js 是什么?
Vue.js 是一套构建用户界面的渐进式框架。采用的是自底向上增量开发的设计(与其他重量级框架不同点)。Vue的核心库只关注图层,不仅易于上手,还便于与第三方库或既有项目整合。
起步
# helloword
注意:不能将id = ‘app’写在body或者html中
<script src = './vue.js'><script> <div id = 'app> <p> {{ message }} </p> </div> <script> var app = new Vue({ el: '#app', message: 'helloword!!!' }) <script>
- 现在的数据和DOM已经绑定在一起了,所有的元素都是响应式
- 文本插值:从控制台输入app.message = '新信息' ,可以修改DOM相应的更新
元素属性:通过v-bind绑定 例如v-bind:title="哈哈哈"
条件循环
- v-if (文本到数据) 提供了一个强大的过渡效果系统,可以在Vue插入/删除/更新时自动应用过渡系统
v-for (结构到数据)
处理用户输入
- v-on 指令绑定一个事件监听器,通过它调用我们Vue实例中定义的方法
- v-on:click = "Add"
v-model 实现表单输入和应用状态之间的双向绑定
实例中的参数
- el: 'id' //el就是 vue 程序的解析入口
- data: { 数据 } //data就是ViewModel
- methods: { 函数 } //函数中的this指向该应用中data的数据
- computed: { 声明一个计算属性函数 }
例子
computed: { // a computed getter reversedMessage: function () { // `this` points to the vm instance return this.message.split('').reverse().join('') } }
filters: { 过滤器函数 }
组件化应用构建
在Vue里,一个组件本质上是一个拥有预定义选项的一个Vue实例
Vue实例
构造器
每个 Vue.js应用都是通过构造函数Vue创建的一个Vue的根实例启动的
var vm = new Vue({ //选项 })
- 没有完全遵循MVVM模式
- 可以扩展Vue构造器,从而用预定义选项创建可复用的组件构造器
所有的 Vue.js 组件其实都是被扩展的 Vue 实例
属性和方法
- 每个Vue实例都会代理其data对象里所有的属性
- 除了data属性外,Vue实例还会暴露了一些有用的实例属性和方法,都带前缀$,以便与代理的data属性区分
不要在实例属性和回调函数中箭头函数,因为箭头函数绑定父上下文,this不会像预想的一样是Vue实例
实例生命周期
Vue.js 是否有“控制器”的概念?答案是,没有。
语法模板
- 在底层的实现上,Vue将模板编译成虚拟DOM渲染函数。结合响应系统,在应用状态发生改变时,Vue能够智能地计算出重新渲染组件的最小代价并应用到DOM操作上。
也可以不用模板,直接写渲染(render)函数,使用可选的JSX语法
插值
# 文本
- 数据绑定最常见的形式就是使用“Mustache”(双大括号)的文本插值
使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新
# 纯HTML
- 双大括号会将数据解析成纯文本,而非HTML。为了输出真正的HTML,需要使用v-html指令
注意:你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容插值。
# 属性
- Mustache不能在HTML属性中使用,应使用v-bind指令
对id,布尔值的属性有效
# 使用Javascript表达式
- 例子
- {{ number + 1 }}
- {{ ok ? 'YES' : 'NO' }}
- {{ message.split('').reverse().join('') }}
表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式。
<!-- 这是语句,不是表达式 --> {{ var a = 1 }} <!-- 流控制也不会生效,请使用三元表达式 --> {{ if (ok) { return message } }}
注意:模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math 和 Date 。你不应该在模板表达式中试图访问用户定义的全局变量。
指令
是带有v-前缀的特殊属性
# 参数
一个指令能接受一个参数,在指令后面以冒号指明
# 修饰符
修饰符(Modifiers)是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()
<form v-on:submit.prevent="onSubmit"></form>
过滤器
Vue.js允许自定义过滤器,可被用作一些常见的文本格式化,用在两个地方:mustache插值和v-bind表达式
<!-- in mustaches --> {{ message | capitalize }} <!-- in v-bind --> <div v-bind:id="rawId | formatId"></div>
- 过滤器函数
- 可以串联
可以接受参数
# 缩写
v-on
<!-- 完整语法 --> <a v-on:click="doSomething"></a> <!-- 缩写 --> <a @click="doSomething"></a>
v-bind
<!-- 完整语法 --> <a v-bind:href="url"></a> <!-- 缩写 --> <a :href="url"></a>
计算属性
计算属性
# 基础例子
# 计算缓存 vs methods
- 计算属性:是基于它们依赖进行缓存的(因依赖改变而重新求值);Date.now()不是响应式依赖
methods:只要发生重新渲染, method调用总会调用执行该函数
# Computed属性 vs Watched 属性
- Watched 属性: 观察和响应Vue实例上的数据变动
缺点:命令式和重复式。更多选择 computed 属性
# 计算 setter
计算属性默认只有getter,根据需求也可以提供一个setter
观察 Watchers
Class 与 Style 绑定
绑定 HTML Class
# 对象语法
- v-bind:class={ 键:值 };可以与普通的class属性共存
- 也可以绑定数据里的一个对象 v-bind:class=“classObject”
也可以绑定一个计算属性
# 数组语法
<div v-bind:class="[activeClass, errorClass]">
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
# 用在组件上
绑定内联样式
# 对象语法
- v-bind:style 的对象语法十分直观,看着非常像CSS,本质是一个 JavaScript 对象,属性名可以用驼峰式或者短横分隔命名
直接绑定到一个样式对象
# 数组语法
<div v-bind:style="[baseStyles, overridingStyles]">
# Vue会自动判断并添加前缀
当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动侦测并添加相应的前缀。
条件渲染
v-if
#
v-if 是一个指令,只能添加到一个元素上,如果像切换到多个元素,需要
v-else 元素必须紧跟在 v-if 或者 v-else-if 元素的后面——否则它将不会被识别。
# v-else-if 指令充当 v-if 的“else-if块”
类似于 v-else,,v-else-if 必须紧跟在 v-if 或者 v-else-if 元素之后。
# 用 key 管理可复用的元素
- 高效渲染元素,对复用已有元素不受从头渲染。
还有别的好处,见官网
v-show
- v-show 是简单地切换元素地 CSS 属性 display。
注意: 不支持
- v-if 是真正地条件渲染(条件块内的所有适当地被销毁和重建);同时也是惰性地;更高地切换开销
v-show:不管初始条件是什么,元素始终会被渲染;更高地初始渲染开销
v-if 与 v-for 一起使用
v-for 具有比 v-if 更高地优先级
列表渲染
v-for
v-for 还支持一个可选的第二个参数为当前项的索引。
<li v-for="(item, index) in items">
- 可以用 of 替代 in。
- Template v-for
- 对象迭代 v-for
- 通过一个对象地属性来迭代
-
<li v-for="value in object">
- 提供第二个的参数为键名
- 第三个参数为索引
- 注意:在遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。
整数迭代 v-for
<span v-for="n in 10">{{ n }}</span>
组件和 v-for
+ <my-component v-for="item in items"></my-component>
key
重用和重新排序现有元素,每项提供一个唯一的 key 属性,需要用 v-bind 来绑定动态值。理想的 key 值是每项都有唯一的id。
<div v-for="item in items" :key="item.id"> <!-- 内容 --> </div>
- 建议尽可能使用 v-for 来提供 key。
key 并不特别与 v-for 关联,key 还有其他用途
数组检查更新
- 变异方法
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
- 重塑数组(非变异方法)
- filter()
- concat()
- slice()
- 不会改变原始数组,总是返回一个新数组
- 注意事项
- 不能检测变动的数组
- 当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如: vm.items.length = newLength
显示过滤/排序结果
- 不能检测变动的数组
如果想要显示一个数组的顾虑或者排序的副本,而不是实际改变或重置原始数据。=>创建返回过滤或排序数组的计算属性
事件处理器
监听事件
v-on
v-on:click="counter += 1"
方法事件处理器
在处理比较复杂的逻辑,直接把 Javascript 代码写在 v-on 是不可行的,可以用 v-on 接受一个定义的方法来调用
v-on:click="greet"
内联处理器方法
v-on:click="say('hi')"
事件修饰符
- .stop() 阻止单击事件冒泡
- .prevent() 提交事件不再重载页面
- .capture() 添加事件侦听器时使用事件捕获模式
- .self() 事件只在该元素本身(而不是子元素)触发时触发回调
.once() 点击事件将只会触发一次
按键修饰符
- 监听常见的键值
Vue 为 v-on 在监听键盘事件时添加按键修饰符:
<input v-on:keyup.13="submit">
按键别名
<input v-on:keyup.enter="submit">
- 全部按键别名
- .enter
- .tab
- .delete (捕获“删除”和“退格”键)
- .esc
- .space
- .up
- .down
- .left
- .right
通过全局 config.keyCodes 对象 自定义按键修饰符别名:
Vue.config.keyCode.f1 = 112
- 2.1.0新增
- .ctrl
- .alt
- .shift
.meta
为什么在 HTML 中监听事件?
- 这种事件监听的方式违背了关注点分离传统理念。不必担心,因为所有 Vue.js 事件处理方式和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。v-on 有几个好处:
- 扫一眼 HTML 模板可以轻松定位到 javascript 代码中对应的方法
- 因为你无法在Javascript中手动绑定事件,你的ViewModel可以式非常纯粹的逻辑,和DOM完全解耦,便于测试
当一个ViewModel被销毁,所有的时间处理器都会自动被删除,无需担心自己如何清理它们
表单控件绑定
基础用法
- v-model 指令在表单控件元素上创建双向数据绑定。负责监听用户的输入事件以更新数据 ,并处理一些极端的例子。
注意:v-model 不关心表单控件初始化所生成的值。因为它会选择 Vue 实例数据来作为具体的值。
# 文本
input type=“text”
# 多行文本
textarea
# 复选框
- input type=checkbox id=“hello”
label for=“hello”
# 单选按钮
- input type=“radio” id=“hello”
label for=“hello”
# 选择列表
- select
option
绑定 value
v-bind:value=“a”
修饰符
# .lazy
转变为在 change 事件中同步
<input v-model.lazy="msg" >
# .number
将用户的输入值转为 Number 类型
<input v-model.number="age" type="number">
# .trim
自动过滤用户的首尾空格
<input v-model.trim="msg">
v-model 与组件
组件
什么是组件
- 组件是Vue.js最强大的功能之一。可以拓展 HTML 元素,可以封装可重用的代码。
在较高层面上,组件是自定义元素,Vue.js 编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性拓展
使用组件
# 注册
创建一个全局组件
Vue.component('my-component', { // 选项 })
确保初始化之前注册组件
# 局部注册
new Vue({ // ... components: { // <my-component> 将只在父模板可用 'my-component': Child } })
# DOM 模板解析说明
限制性元素:
<u l> ,<o l>,<t a b l e> ,<s e l e c t> 限制了能被它包裹的元素, 而一些像 <o p t i o n> 这样的元素只能出现在某些其它元素内部。解决方案:使用特殊的 is 属性
<table> <tr is="my-row"></tr> </table>
这些限制不适用:
+ <script type="text/x-template"> + JavaScript内联模版字符串 + .vue 组件
# data 必须是函数
多个组件共享同一个 data,增加一个 counter 会影响所有的组件。解决方案:每个组件返回一个全新的 data 对象:
data: function () { return { counter: 0 } }
# 构成组件
父子组件:组件 A 在它的模板中使用了组件 B。它们的关系可以总结为 props down,events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。
Prop
# 使用 Prop 传递数据
- 组件实例的作用域是孤立的。
子组件使用父组件的数据,需要通过子组件的 props 选项
# camelCased(驼峰式) vs. kebab-case(短横线隔开式)命名
# 动态 Prop
# 字面量语法 vs 动态语法
<!-- 传递了一个字符串 "1" --> <comp some-prop="1"></comp>
<!-- 传递实际的 number --> <comp v-bind:some-prop="1"></comp>
# 单向数据流
- prop 是单向绑定的:父组件的属性发生变化时,将传导给子组件,不会反过来。--防止子组件无意修改额父组件的状态。
prop 作为初始值传入后,子组件想把它当作局部数据来用;解决方法:定义一个局部变量,并用 prop 的值初始化它
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
prop 作为初始值传入,由子组件处理成其它数据输出,解决方法:定义一个计算属性,处理 prop 的值并返回。
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。
# Prop 验证
自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,应该怎样做?那就是自定义事件!
# 使用 v-on 绑定自定义事件
# 给组件绑定原生事件
v-on:click.native="doThing"
# 使用自定义事件的表单输入组件
# 非父子组件通信
- 在简单的场景夏,可以使用一个空的 Vue 实例作为中央事件总线:
在复杂的情况下,我们应该考虑使用专门的状态管理模式
使用 Slot 分发内容
为了让组件可以组合,我们需要一种方式来混合父组件的内容和子组件自己的模板,这个过程叫做内容分发,使用
# 编译作用域
# 单个 Slot
# 具名 Slot
# 作用域插槽(2.1.0新增)
动态组件
keep-alive
杂项
# 编写可复用组件
- 编写组件时,记住是否要复用组件有好处。一次性组件和其它组件紧密耦合没关系,但是可复用组件应当定义一个清晰的公开接口。
- Vue 组件的 API 来自三个部分 - props,events 和 slots:
- Props 允许外部环境传递数据给组件
- Events 允许组件触发外部环境的副作用
Slots 允许外部环境将额外的内容组合在组件中。
# 子组件索引
# 异步组件
# 组件命名约定
# 递归组件
# 组件间的循环引用
# 内联模板
-这在有很多模版或者小的应用中有用,否则应该避免使用,因为它将模版和组件的其他定义隔离了。
# 对低开销的静态组件使用 v-once