组件-全局注册
<div id="app">
<!-- <Hello> -->
<hello-title>
</div>
<div id="root">
<Hello>
</div>
/* 组件的全局注册 */
// Vue.component( 组件名,组件的选项 )
/*
组件的命名:
1. 大驼峰命名法: Hello HeadTitle
2. 小写加 - : head-title
备注: 如果js中定义的是大驼峰,那么html结构中要使用小写带-
*/
var Hello = Vue.extend({
template: '<div> hello hello hello </div>'
})
// Vue.component('Hello', Hello)
Vue.component('HelloTitle', Hello)
new Vue({
el: '#app'
})
new Vue({
el: '#root'
})
全局注册的简写
Vue.component('Hello', {
template: '<div> hello hello hello </div>'
})
new Vue({
el: '#app'
})
组件-局部注册
<div id="app">
<Hello>
</div>
<div id="root">
<Hello>
</div>
var Hello = Vue.extend({
template: '<div> hello hello hello </div>'
})
new Vue({
el: '#app',
components: {
'Hello': Hello
}
})
new Vue({
el: '#root',
components: {
'Hello': Hello
}
})
局部注册的简写
new Vue({
el: '#app',
components: {
'Hello': {
template: '<div> hello hello hello </div>'
}
}
})
new Vue({
el: '#root',
components: {
'Hello': {
template: '<div> hello hello hello </div>'
}
}
})
组件的-template选项
<div id="app">
<Hello></Hello>
<template>
<p> 456 </p>
</template>
</div>
<template id = "hello">
<!-- template标签的直接子元素只能有一个 -->
<div>
今天是个好日子
<p> 123 </p>
</div>
</template>
/* template标签在实例范围内是会被解析,将来不会在页面出现,但是实例范围外会出现 */
Vue.component('Hello',{
template: '#hello'
})
new Vue({
el: '#app'
})
组件的使用规则-is规则
<div id="app">
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<!-- <Hello></Hello> 这个是不行的 -->
<tr is = "Hello"></tr> //is规则可以实现
</table>
</div>
<template id = "hello">
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</template>
/*
* html中哪些规定了自己的直接子元素的标签,是不能直接放组件的
解决: 通过is属性绑定一个组件
*/
Vue.component('Hello',{
template: '#hello'
})
new Vue({
el: '#app'
})
组建的选项
- data选项为什么是一个函数?
- 组件是一个聚合体,也是一个整体,它需要一个独立的作用空间,也就是它的数据需要是独立的,目前js的最大特点是函数式编程,而函数恰好提供了一个独立作用域,所以我们data在出根组件外都是函数
- 为什么data函数需要返回一个返回值,返回值还是对象,不能是数组吗?
- Vue通过es5的Object.definePerproty属性对一个对象进行getter和setter设置,而data选项是作为Vue深入响应式核心的选项
两个组件的嵌套-全局
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> father </h3>
<hr>
<Son/>
</div>
</template>
<template id="son">
<h5> son </h5>
</template>
/* *****组件之间的嵌套要将子组件以标签化的形式放在父组件的模板中使用***** */
Vue.component('Father',{
template: '#father'
})
Vue.component('Son',{
template: '#son'
})
new Vue({
el: '#app'
})
两个组件的嵌套-局部
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> Father </h3>
<hr>
<Son/>
</div>
</template>
<template id="son">
<h3> Son </h3>
</template>
new Vue({
el: '#app',
components: {
'Father': {
template: '#father',
components: {
'Son': {
template: '#son'
}
}
}
}
})
父子组件通信
- 过程
- 父组件将自己的数据同 v-bind 绑定在 子组件身上
- 子组件通过 props属性接收
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> Father </h3>
<hr>
<Son :give="money" />
</div>
</template>
<template id="son">
<div>
<h3> Son </h3>
<p> 收到了 {{ give }} 元钱</p>
</div>
</template>
Vue.component('Father', { //这里采用了全局注册组件
template: '#father',
data() {
return {
money: 9999999
}
}
})
Vue.component('Son', {
template: '#son',
props: ['give']
})
new Vue({
el: '#app'
})
- props属性数据验证
- 验证数据类型
- 验证数据大小【 判断条件 】
验证数据类型:
props: {
'money': Number //String Boolean Object Array
}
验证数据大小:
props: {
'aa': {
validator ( val ) {
return val > 3000 //大于3000才显示
}
}
}
子父组件通信
- 过程
- 是通过自定义事件
- 事件的发布
- 通过绑定元素身上实现
- 事件的订阅
- 通过this.$emit触发
- 事件的发布
- 是通过自定义事件
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> Father </h3>
<hr>
<p> 收到工资 {{ shouru }} 元整</p>
<p> 余额为 {{ shouru + 88866598.5 }} 元</p>
<Son @xinshui="get"/>
</div>
</template>
<template id="son">
<div>
<h3> Son </h3>
<button @click="fagongzi">发工资</button>
</div>
</template>
Vue.component('Father', {
template: '#father',
data() {
return {
shouru: 0
}
},
methods: {
get(val) {
this.shouru = val
}
}
})
Vue.component('Son', {
template: '#son',
data() {
return {
gongzi: 99999999999
}
},
methods: {
fagongzi() {
this.$emit('xinshui', this.gongzi)
}
}
})
new Vue({
el: '#app'
})
子父组件通信的精髓在于:
在父组件中,定义一个方法,以自定义事件的形式传给子组件(在子组件的模板中以自定义事件的形式传递该方法),然后在子组件中通过定义一个方法,在方法中用this.$emit()触发父组件传递过来的事件,最后在子组件的模板中选择触发方式,触发刚才子组件定义的方法。
非父子组件通信
- ref绑定
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> father组件 </h3>
<hr>
<!-- 使用自定义属性形式将一个方法传递给子组件 -->
<Girl :kick = "getSon"></Girl>
<hr>
<Son ref = "son"></Son>
</div>
</template>
<template id="son">
<div>
<h3> son组件 </h3>
<img v-if = "flag" src="./img/photo04.jpg" alt="">
<img v-else src="./img/photo05.jpg" alt="">
</div>
</template>
<template id="girl">
<div>
<h3> girl组件 </h3>
<button @click = "hit"> 揍弟弟 </button>
</div>
</template>
<script>
Vue.component('Father', {
template: '#father',
methods: {
getSon() {
console.log(this)
this.$refs.son.changeFlag()
}
}
})
Vue.component('Son', {
template: '#son',
/* 组件是独立的,自己的数据自己改 */
data() {
return {
flag: true
}
},
methods: {
changeFlag() {
this.flag = !this.flag
}
}
})
Vue.component('Girl', {
template: '#girl',
props: ['kick'],
methods: {
hit() {
this.kick()
}
}
})
new Vue({
el: '#app'
})
</script>
通过ref绑定子组件的所有方法,这样定义在子组件里的事件就可以被父组件调用,然后父组件用自定义属性的方式将一个方法传递给另一个子组件
- bus事件总线
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> father组件 </h3>
<hr>
<!-- 使用自定义属性形式将一个方法传递给子组件 -->
<Girl></Girl>
<hr>
<Son></Son>
</div>
</template>
<template id="son">
<div>
<h3> son组件 </h3>
<img v-if = "flag" src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3872048339,4140466773&fm=26&gp=0.jpg" alt="">
<img v-else src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2438534582,3797477605&fm=26&gp=0.jpg" alt="">
</div>
</template>
<template id="girl">
<div>
<h3> girl组件 </h3>
<button @click = "hit"> 揍弟弟 </button>
</div>
</template>
<script>
/* 定义了实例bus - bus上有 $on $emit */
var bus = new Vue()
Vue.component('Father',{
template: '#father',
})
Vue.component('Son',{
template: '#son',
/* 组件是独立的,自己的数据自己改 */
data () {
return {
flag: true
}
},
mounted () {
/* mounted表示挂载结束,也就是我们能看到界面了,也就是事情做完了 */
/* 这个函数会自动执行 */
var _this = this
/* 通过bus绑定了自定义事件 */
bus.$on('ku',function () {
_this.flag = !_this.flag
})
}
})
Vue.component('Girl',{
template: '#girl',
methods: {
hit () {
bus.$emit('ku')
}
}
})
new Vue({
el: '#app'
})
</script>
bus上有
o
n
和
on和
on和emit
子组件通过
o
n
绑
定
事
件
,
另
一
个
子
组
件
通
过
on绑定事件,另一个子组件通过
on绑定事件,另一个子组件通过emit调用该方法,并在模板中触发
在组件上实现原生事件
<div id="app">
<Hello :name = "name" @click.native = "changeName"></Hello>
</div>
<template id="hello">
<div style = "width: 100px;height: 100px;background:red;">
<p> {{ name }} </p>
</div>
</template>
<script>
Vue.component('Hello',{
template: '#hello',
props: ['name']
})
new Vue({
el: '#app',
data: {
name: '骏哥'
},
methods: {
changeName () {
this.name = "西阁"
}
}
})
</script>
通过添加.native 调用方法
动态组件
<div id="app">
<select name="" id="" v-model = "val">
<option value="father"> father </option>
<option value="son"> son </option>
</select>
<component :is = "val"></component>
</div>
<script>
Vue.component('Father',{
template: '<div> father </div>'
})
Vue.component('Son',{
template: '<div> son </div>'
})
new Vue({
el: '#app',
data: {
val: 'father'
}
})
</script>
通过<component :is = ""></component>实现组件的动态切换
动态缓存组件
<div id="app">
<select name="" id="" v-model="val">
<option value="Father"> father </option>
<option value="Son"> son </option>
</select>
<keep-alive :include="val">
<component :is="val"></component>
</keep-alive>
</div>
<script>
Vue.component('Father', {
template: '<div> father </div>',
activated() {
/* !keep-alive组件专用 */
console.log('father-activated')
},
})
Vue.component('Son', {
template: '<div> son </div>',
activated() {
/* !keep-alive组件专用 */
console.log('son-activated')
},
})
new Vue({
el: '#app',
data: {
val: 'Father'
},
activated() {
/* !keep-alive组件专用 */
console.log('inactived')
},
deactivated() {
/* !keep-alive组件专用 */
console.log("兵哥: deactivated -> deactivated")
}
})
</script>
/* !keep-alive组件可以实现组件的缓存,让组件的切换能够更快
keep-alive会激活两个钩子函数 activated deactivated
activated 激活,正在显示的
deactivated keep-alive被停用
*/
过渡效果
<div id="app">
<button @click = "changeFlag"> changeFlag </button>
<!-- mode 有两个值 in-out out-in -->
<transition
name = "xige"
mode = "in-out"
enter-active-class = "animated fadeIn"
leave-active-class = "animated fadeOut"
>
<p v-if = "flag"></p>
</transition>
</div>
<script>
new Vue({
el: '#app',
data: {
flag: true
},
methods: {
changeFlag () {
this.flag = !this.flag
}
}
})
</script>
通过引入animate.css文件,和在<transition>标签里定义属性,实现动画
过滤器
- 局部定义
<div id="app">
<button @click = "getTime"> 获得时间 </button>
<p> {{ time | timerFilter }} </p>
</div>
<script>
/* 过滤器
全局定义
Vue.filter(过滤器名称,回调函数)
*/
new Vue({
el: '#app',
data: {
time: ''
},
methods: {
getTime () {
this.time = new Date()
}
},
filters: {
'timerFilter': function ( val ) {
var date = new Date( val )
if ( val ) {
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月' + date.getDate() + '日'
} else {
return ''
}
}
}
})
</script>
- 全局定义
<div id="app">
<button @click = "getTime"> 获得时间 </button>
<p> {{ time | timerFilter( '-' ) }} </p>
</div>
<script>
/* 过滤器
全局定义
Vue.filter(过滤器名称,回调函数)
*/
Vue.filter('timerFilter',function ( val,type ) {
console.log("兵哥: val", val) //val就是格式化目标的值
var date = new Date( val )
if ( val ) {
return date.getFullYear() + type + (date.getMonth() + 1) + type + date.getDate()
} else {
return ''
}
})
new Vue({
el: '#app',
data: {
time: ''
},
methods: {
getTime () {
this.time = new Date()
}
}
})
</script>
插槽
插槽,给组件的内容预留一个空间
- 普通插槽
<div id="app">
<Hello> <p> 你好 </p> </Hello>
</div>
<template id="hello">
<div>
<h3> hello组件 </h3>
<!-- 插槽,给组件的内容预留一个空间 -->
<slot></slot>
</div>
</template>
<script>
Vue.component('Hello',{
template: '#hello'
})
new Vue({
el: '#app'
})
</script>
- 命名插槽
<div id="app">
<Hello>
<header slot = "header"> 头部 </header>
<footer slot = "footer">底部</footer>
</Hello>
</div>
<template id="hello">
<div>
<slot name = "header"></slot>
<h3> hello组件 </h3>
<!-- 插槽,给组件的内容预留一个空间 -->
<slot name = "footer"></slot>
</div>
</template>
<script>
Vue.component('Hello',{
template: '#hello'
})
new Vue({
el: '#app'
})
</script>
- 作用域插槽
<div id="app">
<Hello>
<template v-slot:default = "scope">
<p> {{ scope.money }} </p>
</template>
</Hello>
</div>
<template id="hello">
<div>
<slot :money = "money"></slot>
</div>
</template>
<script>
/*
作用域插槽可以让本只能在组件的模板中使用的数据,应用到组件的内容中
*/
Vue.component('Hello',{
template: '#hello',
data () {
return {
money: 100000
}
}
})
new Vue({
el: '#app'
})
</script>