vu 两大特性:
1 . 指令 – 用来操作 dom
2 . 组件 – 组件是 html css js的聚合体
为什么要使用组件?
- 组件可以在项目中进行复用
- 加快项目进度
- 将一个具备完整功能的项目的一部分进行多处使用
要想使用组件化,那么这个组件是完整的
组件中的根元素必须是唯一
组件要先注册,再实例化,要在实例范围内执行
vue 借鉴 react ,组件以标签的形式呈现的。
//组件使用前必须先注册
Vue.component(组件名称,组件配置)
var Hello = Vue.extend({})
Vue.compoent('Father', Hello)
可以简化
Vue.componet('Father', {
template
})
组件的创建
-
全局注册
所有实例都可以使用
Vue.componet('Father', { template })
-
局部注册
在实例中间使用 components:{ }
new Vue({ el: '#app', components: { 'Father': { template: '<div>局部组粗</div>' } } })
组件的嵌套
在父组件里放子组件: 将子组件以标签的形式放在父组件中
全局嵌套
<div id="app">
<Father></Father>
</div>
<template id="father">
<h3>这里是父组件模板</h3>
</Son>
</template>
Vue.component('Father',{
template: '#father'
})
Vue.component('Son', {
template:'<div> son </div>'
})
局部嵌套
new Vue([
el: '#app',
compoents: {
template: '<div> father 组件 </Son> </div>',
components: {
'Son': {
template: '<div> son 组件 </div>
}
}
}
])
is 规则
ul>li ol>li table>tr>td select>option
如上直属父子级如果直接组件以标签化形式使用,会出现 bug
解决:需要通过 is 属性来绑定一个组件
组件的一些特殊使用规则 【
组件通信
1. 为什么要进行组件通信?
- 每个组件都是一个独立功能的整体,当我们要将这些组件拼接在一起时,就需要在这些组件之间建立通信
2 组件的通信有哪些?
1. 父子组件通信
使用 props 来实现
//1.在父组件的模板中将数据用单项数据绑定的形式(v-bind)绑定到子组件上
<Son :aa = "money" :maskFlag = "maskFlag"/>
Vue.component('Father',{
template: '#father',
data () {
return {
money: 2000,
}
}
})
Vue.component('Son',{
template: '#son',
props: ['aa','maskFlag']
})
2. 子父组件通信
使用做自定义事件通信
-
在父组件模板中,通过事件绑定的形式,绑定一个自定义事件在子组件身上
<Son @a = 'fn'> //注意: fn 是在父组件配置项 methods 中定义
-
在子组件的配置项 methods 中写一个事件处理程序,在事件处理程序中 使用 $emit() 触发父组件中绑定的自定义事件
Vue.component('Son',{ template: '#son', props: ['aa','maskFlag'] })
-
将子组件定义事件处理函数 ,绑定到子组件的按钮上
3. 非父子组件通信
1.ref 链
父组件通过 ref 链得到一个子组件的数据,在把数据发送到另一个子组件上,就可以实现非父子组件的通信,当是如果层级太多,就比较繁琐
2.bus 事件总线
通过 bus. o n 来 定 义 事 件 , 通 过 on 来定义事件,通过 on来定义事件,通过emit 来触发事件
-
在其中一个组件的 mounted 钩子函数上进行事件声明
Vue.component('sma', { template: '#sma', data() { return { flag: false } }, mounted () { //在 mounted 钩子函中事件声明 let _this = this bus.$on('aa', function(){ // 事件声明 _this.flag = true; }) } })
-
在另一个组件中,通过 bus.$emit(‘aa’) 来触发这个事件
4. 多组件状态共享 ( 多组件共有同一个数据)
vuex
5. 非常规通信方式
不推荐:因为 mvvm 框架是单项数据流
1. 父子通信
父组件窗体一个 对象类型 给子组件,子组件通过 props 接收,
会发现:子组件修改数据时,父组件的数据也会发生改变
因为父组件传递给子组件的是一个对象引用地址
<body>
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3>这是fatcher 组件</h3>
<p>父组件小金库 ---{{ xiaojingku.money }}</p>
<Son :xiaojingku="xiaojingku"></Son>
</div>
</template>
<template id="son">
<div>
<h3>这是 son组件</h3>
<button >give</button>
<input type="text" v-model="xiaojingku.money">
<p>son : {{ xiaojingku.money}}</p>
</div>
</template>
</body>
<script>
2. 子父通信
父组件将一个方通过属性绑定的形式给了子组件,子组件用 props 接收方法,在子组件中调用方法并传参
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3>这是fatcher 组件</h3>
<Son :add="add"></Son> //1.将方法绑定到子组件上
{{ n }} //2000
</div>
</template>
<template id="son">
<div>
<h3>这是 son组件</h3>
<button @click="add(money)">give</button> //3. 子组件调用传来的方法,并传值
</div>
</template>
</body>
<script>
Vue.component('Father', {
template: '#father',
data() {
return {
n: 0
}
},
methods: {
add (val) {
this.n = val;
}
}
})
Vue.component('Son', {
template: '#son',
data() {
return {
money: 1000
}
},
props: ['add'] //2. 子组件接收方法
})
new Vue({
el: '#app',
})
3. 动态组件
- 什么是动态组件?
可以修改的组件
- 使用
vue 提供过了 一个 compoent 标签(组件) + is 属性 来实现
<body>
<div id="app">
<button @click="change" >切换</button>
<keep-alive> <kee-alive> 组件 可以对组件进行浏览器缓存,在切换组件时就可以提高效率。
<component :is = "type"></component>
</keep-alive>
</div>
</body>
<script>
Vue.component('A',{
template: '<div>A组件啊</div>'
})
Vue.component('B',{
template: '<div>B组件啊啊</div>'
})
new Vue({
el: '#app',
data: {
type: 'A',
},
methods: {
change(){
this.type = this.type === 'A' ? 'B':'A';
}
}
})
</script>
语法糖: 对代码的另一种语法实现,功能保持不变,提高代码的可读性,减少出错
组件中data定义是一个函数?
因为组件是一个独立的个体,应该拥有的自己独立的作用域数据。
为什么data 为什么要有 return,return 的还是一个对象?
1. 因为Vue 是通过observer 来观察 data选项的,所以必须要有 返回值。
2. 应为Vue 要通过 es5 的Object.defineProperty 属性对对象 进行getter 和 setter 设置,这个属性传的第一个参数是一个对象。
自定义事件的发布
- 通过$on 发布, $emit 触发
vm.$on(自定义事件名称,自定义事件处理函数)
vm.$on('a', function() {
console.log( 'aaa');
})
vm.$emit(自定义事件的名称,自定义事件需要的参数);
- 把事件在组件上定义,通过 $emit() 触发
app实例的手动挂载
new Vue({
}).$mount('#app');
属性验证
-
props: [ ‘msg’ ] 只是单纯的接收了一个父组件传来的数据,没有验证
-
props: { attr: attType } 进行数据类型验证
-
props: { type: typeType, defalut: value } 为数据设置初始值
-
props: { varlidator ( val ) { return boolean }} 对数据进行条件比较,return booblean
-
第三方包: vue-validata vee-validate…
Vue.component('Son', { template: '#son', props:{ // key: value 'money': Number, 'n': { validator ( val ) { //属性验证函数,一般用于条件比较 return val > 200 } }, 'num': { type: Number, default: 200 } } })
过滤器
-
什么是过滤器?
-
用来格式化数据的一个函数
vue 1.x 借鉴啦 angular, 提供了 10 个过滤器( 日期,小数点位数保留,货币,大小写)
vue 2.x 废弃了 这10个过滤器,提供自定义过滤器的方式
-
-
使用方式
过滤器要想获得我们的数据,要通过一个叫 ‘管道符 | ’ 来获取数据
过滤器是对已有的数据进行格式化,必须先得到数据在可视化
1. 全局定义过滤器 ```vue // Vue.filter(过滤器名称, 回调函数); <body> <div id="app"> <p>{{ time | timeFilter("/") }}</p> </div> </body> <script> Vue.filter('timeFilter', (val, type) => { let data = new Date(); return data.getFullYear() + type + ( data.getMonth() + 1 ) + type + data.getDate(); }) ```
-
局部定义过滤器
<body> <div id="app"> <p> {{time | timeFilter('-')}}</p> </div> </body> <script> new Vue({ el: '#app', data: { time: Date.now() }, filters: { 'timeFilter': function (val, type) { let date = new Date(); return date.getFullYear() + type + date.getMonth() + 1 + type + date.getDate(); } } })
solot 插槽
-
-
作用/概念: 预先将将来要是用的内容进行保留
-
具名插槽: