这是我的个人博客,有兴趣的可以去看看,说不定有收获。
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统
生命周期
注意事项:
- 不要在选项属性或回调上使用箭头函数,因为箭头函数没有
this
。 - 生命周期钩子的
this
上下文指向调用它的Vue
实例
图示:
模板语法
Vue.js
使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue
实例的数据。
在底层的实现上,Vue
将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue
能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
指令>)
Vue
的指令有:
v-if
v-else
v-else-if
v-on
v-bind
v-for
v-show
v-once
v-model
v-text
v-html
v-model
v-slot
v-pre
v-cloak
动态参数
从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数:
<a v-bind:[attributeName]="url"> ... </a>
计算属性和侦听器
计算属性
- 处理复杂的逻辑
- 计算属性是基于它们的响应式依赖进行缓存的,在相关响应式依赖发生改变时它们才会重新求值
- 默认只有 getter ,不过在需要时你也可以提供一个 setter
侦听器
- 观察和响应 Vue 实例上的数据变动
- 当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
Class和Style的绑定
对象语法
<div v-bind:class="{ active: isActive }"></div>
绑定的数据对象不必内联定义在模板里:
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
也可以配合使用三元表达式,数组语法中也可以使用对象语法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
当 v-bind:style
使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform
,Vue.js 会自动侦测并添加相 应的前缀。
从 2.3.0 起你可以为 style
绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那 么就只会渲染 display: flex
。
用在组件上
当在一个自定义组件上使用 class
属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类 不会被覆盖。
条件渲染
v-if
/v-else-if
/v-else
v-show
v-show
不支持 <template>
元素,也不支持 v-else
。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。
不推荐v-if
和v-for
一起使用,同时存在时,v-for
具有更高的优先级。
列表渲染
数组
<li v-for="(item, index) in arr">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
对象
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
在组件上使用
任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要 使用 prop。
不自动将 item
注入到组件里的原因是,这会使得组件与 v-for
的运作紧密耦合。明确组件数据的来源能够使 组件在其他场合重复使用。
维护状态
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变, Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正 确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲 染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个 唯一 key
属性
建议尽可能在使用 v-for
时提供 key
attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
事件处理
事件修饰符>)
.stop
.prevent
.capture
.selt
.once
.passive
按键修饰符>)
.enter
.tab
-
.delete
(捕获删除和退格键) .esc
.space
.up
.down
.left
.right
系统修饰符>)
.ctrl
.alt
.shift
.meta
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件。
鼠标按钮修饰符
.left
.right
.middle
为什么在 HTML 中监听事件?
你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。实际上,使用 v-on
有几个好处:
- 扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
- 因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
- 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。
表单输入绑定
修饰符
-
.lazy
<!-- 在“change”时而非“input”时更新 --> <input v-model.lazy="msg" >
-
.number
自动将用户的输入值转为数值类型。如果这个值无法被
parseFloat()
解析,则会返回原始的值。<input v-model.number="age" type="number">
-
.trim
自动过滤用户输入的首尾空白字符
<input v-model.trim="msg">
组件注册
组件命名>)
全局注册
Vue.component('my-component-name', {
// ... 选项 ...
})
全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生
局部注册
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
局部注册的组件在其子组件中不可用
Prop
大小写
当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命 名) 命名:
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
传入一个对象的所有属性
如果你想要将一个对象的所有属性都作为 prop 传入,你可以使用不带参数的 v-bind
(取代 v-bind:prop- name
)
post: {
id: 1,
title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
单向数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但 是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件 中改变这个对象或数组本身将会影响到父组件的状态。
Prop验证
'null'、'undefind'会通过任何类型的检查
非Prop的特性)
一个非 prop 特性是指传向一个组件,但是该组件并没有相应 prop 定义的特性。
因为显式定义的 prop 适用于向一个子组件传入信息,然而组件库的作者并不总能预见组件会被用于怎样的场 景。这也是为什么组件可以接受任意的特性,而这些特性会被添加到这个组件的根元素上。
对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type="text"
就 会替换掉 type="date"
并把它破坏!庆幸的是,class
和 style
特性会稍微智能一些,即两边的值会被合 并起来
如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false
。
自定义事件
事件名
不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所 用的名称。推荐始终使用 kebab-case 的事件名。
自定义组件使用v-model
一个组件上的 v-model
默认会利用名为 value
的 prop 和名为 input
的事件,但是像单选框、复选框等类型 的输入控件可能会将 value
特性用于不同的目的。model
选项可以用来避免这样的冲突:
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
将原生事件绑定到组将上)
.sync
修饰符
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。
Slot
注意 v-slot 只能添加在一个 <template> 上 (只有一种例外情况)
编译作用域
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
后备内容
具名插槽
作用域插槽
动态组件/异步组件
在动态组件上使用keep-alive
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
异步组件
- 局部注册的时候,你也可以直接提供一个返回
Promise
的函数:
new Vue({
// ...
components: {
'my-component': () => import('./my-async-component')
}
})
- 全局注册的时候,你也可以在工厂函数中返回一个
Promise
,所以把 webpack 2 和 ES2015 语法加在一起,我们可以写成这样:
Vue.component(
'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
处理加载状态
处理边界情况
访问根实例
this.$root
访问父级组件实例
this.$parent
访问子组件实例或子元素
你可以通过 ref
特性为子组件赋予一个 ID 引用
<base-input ref="usernameInput"></base-input>
this.$refs.usernameInput
当 ref
和 v-for
一起使用的时候,你得到的引用将会是一个包含了对应数据源的这些子组件的数组。
$refs
只会在组件渲染完成之后生效,并且它们不是响应式的。
依赖注入
父组件provide
注入,子组件 inject
接受。
程序化的事件侦听器
循环引用
- 递归组件
- 组件间的相互引用
模板定义的替代品
- 内联模板 inline-template 内联模板需要定义在 Vue 所属的 DOM 元素内。
- x-template 在一个
<script>
元素中,并为其带上text/x-template
的类型,然后通过一个 id 将模板引用过去 x-template 需要定义在 Vue 所属的 DOM 元素外。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。