目录
八、过滤器
可被用于一些常见的文本格式化。
过滤器可以用在两个地方:双花括号插值和 v-bind
表达式
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
过滤器可以串联:
{{ message | filterA | filterB }}
可以接收参数:
{{ message | filterA('arg1', arg2) }}
全局定义
Vue.filter('capitalize', function (value) { })
局部定义
filters: {
capitalize: function (value) { }
}
九、Vue生命周期的介绍
四个钩子 - 生命周期:
beforeCreated():表示实例出现在内存之前
created():表示实例出现在内存中,但是没有被渲染到页面中。
beforeMount():实例已经渲染到页面之前。
mounted():实例已经被渲染到页面中。
beforeUpdated():实力更新之前。
updated():实例更新了,比如点击按钮,页面数字 + 1 操作,可以拿到更新后的数据。
beforeDestroyed():实例消亡之前。
destroyed():实例消亡了,从页面中消失了。可结合 v-if 控制当前模块在页面中是否显示,消失就触发 destoryed()。
十、自定义指令
全局指令
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', { })
局部指令
directives: {
focus: {}
}
在模板中任何元素上使用新的 v-focus
指令,如下:
<input v-focus>
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 -
update
:组件更新时调用 -
componentUpdated
:组件的与子组件更新后调用。 -
unbind
:只调用一次,指令与元素解绑时调用。
执行顺序:
页面加载时 : bind inserted
组件更新时 : update componentUpdated
卸载组件时 : unbind
钩子函数参数
指令钩子函数会被传入以下参数:
-
el
:指令所绑定的元素,可以用来直接操作 DOM。 -
binding
:一个对象,包含以下属性:name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
-
vnode
:Vue 编译生成的虚拟节点。 -
oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。除了
el
之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的dataset
来进行
函数简写
在 bind
和 update
时触发相同行为,而不关心其它的钩子。可以这样写:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
参数传递
<p v-color = "{color:'green'}">json对象参数传递</p>
<p v-color = "['blue','red']">传递数组参数</p>
<p v-color = "msg">传递变量参数</p>
数据都会封装到binding对象的value属性中
十一、组件
1 注册组件
全局注册
Vue.component('my-component-name', { /* ... */ })
局部注册
//通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
//然后在 components 选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
}
})
局部注册的组件在其子组件中不可用
2 创建组件
一: 采用Vue.component(“组件名”,{ }) 的方式
<div id='app'>
<mycom1> </mycom1>
</div>
<script>
Vue.component("mycom1",{
template: '<div>采用简写的方式创建组件</div>'
})
</script>
二:采用template标签(模板分离)
<!--template模板的位置在app外-->
<template id = "tmp1">
<p>我是采用template标签模板创建的组件</p>
</template>
<script>
Vue.component("mycom3",{
template: '#tmp1'
})
</script>
三:采用script标签来创建组件
<script type = "x-template" id= "tmp2">
<div>我是采用script标签创建的组件</div>
</script>
<script>
Vue.component("mycom4",{
template: '#tmp2'
})
</script>
3 组建嵌套
组件 mycom2 在 mycom1 中嵌套:
<div id='app'>
<mycom1></mycom1>
</div>
let com1 = {
template : "<p>我是组件一<mycom2></mycom2>......</p>"
}
let com2 = {
template : "<p>我是组件二</p>"
}
Vue.component("mycom1",com1) ;
Vue.component("mycom2",com2) ;
var vm = new Vue({
el: '#app'
})
嵌套限制
根元素 : Vue强制要求每一个Vue实例(组件本质上就是一个Vue实例)需要有一个根元素
Data: 一般地,我们在Vue实例对象或Vue组件对象中,我们通过data来传递数据
原生事件 : 有时候,可能想在某个组件的根元素上监听一个原生事件。直接使用v-bind指令是不生效的,可以使用 .native 修饰 v-on指令
5 组件命名
-
使用 kebab-case(短横线分隔命名)
Vue.component('my-component-name', {})
引用组件时可写为:<my-component-name>
-
使用 PascalCase(驼峰命名法)
Vue.component('MyComponentName', { })
引用组件时可写为:
<my-component-name>
和<MyComponentName>
。
注意:在 DOM (即非字符串的模板) 中使用时只有kebab-case 是有效的。
6 自定义属性props
prop 定义了这个组件有哪些可配置的属性,组件的核心功能也都是它来确定的。写通用组件时,props 最好用对象的写法。
props 可以显示定义一个或一个以上的数据,对于接收的数据,可以是各种数据类型,同样也可以传递一个函数。通过一般属性实现父向子通信;通过函数属性实现子向父通信
prop类型
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
传递静态或动态 Prop
<!-- 给 prop 传入一个静态的值 -->
<blog-post title="My journey with Vue"></blog-post>
<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"> </blog-post>
<!-- 动态赋予一个复杂表达式的值 -->
<blog-post v-bind:title="post.title + ' by ' + post.author.name" > </blog-post>
即便数字,布尔值,数组,对象都是静态的,我们仍然需要 v-bind
来告诉 Vue这是一个 JavaScript 表达式而不是一个字符串。
Prop 验证
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
//从父级传入的 type,它的值必须是指定的 'success', 'warning', 'danger'中的一个,
//如果传入这三个以外的值,都会抛出一条警告
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
data与props区别
相同点
两者选项里都可以存放各种类型的数据,当行为操作改变时,所有行为操作所用到和模板所渲染的数据同时都会发生同步变化。
不同点
data 被称之为动态数据,在各自实例中,在任何情况下,我们都可以随意改变它的数据类型和数据结构,不会被任何环境所影响。
props 被称之为静态数据,在各自实例中,一旦在初始化被定义好类型时,基于 Vue 是 单向数据流,在数据传递时始终不能改变它的数据类型,而且不允许在子组件中直接操作 传递过来的props数据,而是需要通过别的手段,改变传递源中的数据
7 组件的钩子函数
-
beforeCreate与created
(1) beforeCreate 为组件完全创建前调用的函数,使用不多,但常用于定时器;
(2) created 为组件完全创建后调用的函数,此时可以获取后端数据然后对组件中的数据属性进行赋值以渲染视图层; -
beforeMount与mounted
(1) beforeMount 为组件以及组件数据挂载到DOM之前调用的函数;
(2) mounted 为组件以及组件数据挂载到DOM后调用的函数 -
beforeUpdate与updated
(1) beforeUpdate 为更新DOM之前调用的函数,应用为获取原始DOM;
(2) updated 为更新DOM之后调用的函数,应用为获取最新的DOM; -
beforeDestroy与destroyed
(1) beforeDestroy 为组件销毁之前调用的函数,不常用;
(2) destroyed 为组件销毁之后调用的函数,常用在页面定时器的销毁; -
activated与deactivated
若页面中某一组件频繁的被创建和销毁,这将非常消耗性能。因此我们考虑将销毁的组件状态缓存起来, Vue中提供了keep-alive标签对,在使用组件的时候直接将组件标签嵌套在该标签中,则能防止组
件在频繁创建和销毁的时候不会重复的渲染DOM。一旦使用了这一标签对后,组件的创建便成了激活,销
毁则成了停用。组件在激活的时候调用的钩子函数是activated,在停用时调用的函数则是deactivated。
8 父子组件的参数传递
父组件向子组件传递数据分为两种方式:动态和静态
动态绑定:在模板中,要动态地绑定父组件的数据到子组件模板的 props,和绑定 Html 标签特性一样,使用v-bind绑定;
9 单向数据流
-
数据从父级组件传递给子组件,只能单向绑定。子组件内部不能直接修改从父级传递过来的数据。所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
-
每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
10 修改prop
方法一:**这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。**在这种情况下,最好定义一个本地的 data property 并将这个 prop 用作其初始值。
方法二:**这个 prop 以一种原始的值传入且需要进行转换。**在这种情况下,最好使用这个 prop 的值来定义一个计算属性。
方法三: 使用**.sync**。作用 : vue的prop是单向下行绑定:父级的prop的更新会向下流动到子组件中,但是反过来不行。可是有些情况,我们需要对prop进行“双向绑定”。这个时候,就可以用.sync来解决,利用 EventBus,当子组件触发事件时,父组件会响应事件并实现数据更新,避免了子组件直接修改父组件传过来的内容
方法4:将父组件中的数据包装成对象传递给子组件
这是因为在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的
prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。比如上例中在子
组件中修改父组件传递过来的数组arr,从而改变父组件的状态 示例见下
11 $emit的用法
1、父组件可以使用 props 把数据传给子组件。
2、子组件可以使用 $emit 触发父组件的自定义事件。
vm.$emit( event, arg ) //触发当前实例上的事件
vm.$on( event, fn );//监听本组件event事件后运行 fn;
12 动态组件
-
通过使用保留的 元素,动态地绑定到它的 is 特性,可以让多个组件使用同一个挂载点,并动态切换
-
保留切换出去的组件,避免重新渲染
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数。
13 插槽(slot)
- 单个slot
slot相当于子组件设置了一个地方,如果在调用它的时候,往它的开闭标签之间放了东西,那么它就把这些东西放到slot中。 - 当子组件中没有slot时,父组件放在子组件标签内的东西将被丢弃;
- 子组件的slot标签内可以放置内容,当父组件没有放置内容在子组件标签内时,slot中的内容会渲染出来;
当父组件在子组件标签内放置了内容时,slot中的内容被丢弃
具名插槽
<slot>
元素有一个特殊的 attribute:name
。这个 attribute 可以用来定义额外的插槽。
<div id="app">
<my-component>
<h1 slot="header">这里可能是一个页面标题</h1>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<p slot="footer">这里有一些联系信息</p>
</my-component>
</div>
<script>
new Vue({
el: "#app",
data: {},
components: {
'my-component': {
template: `
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div> `
}
}
})</script>
作用域插槽
作用域插槽也是一个插槽slot,但是他可以把数据传递给到父组件的特定元素内,然后有父组件决定如何渲染这些数据。
1.首先,子组件的slot需要有一些特性(prop)
2.父组件在调用子组件时,需要在里面添加一个template元素,并且这个template元素具有scope特性
scope特性的值,就代表了所有子组件传过来的数据组成的对象。相当于:
props={
text:' ',
message:' ',
}
3.最后,父组件就可以在template中渲染子组件传过来的数据了
<div id="app">
<my-component4>
<template slot-scope = "{text,message}">
{{text}} :: {{message}}
</template>
<template slot-scope = "props">
{{props.text}} ::: {{props.message}}
</template>
</my-component4>
</div>
<script>
Vue.component("my-component4", {
template: `
<div>
<slot :text = "hello" message = "world111"></slot>
</div>
`,
})
new Vue({
el: "#app",
})
</script>