组件的使用
Vue中使用组件的三大步骤:
1.定义组件
2.注册组件
3.使用组件
如何定义一个组件:
使用Vue.extend(options)创建,传入options和new Vue(options)时传入的那个options几乎一样,但是也有区别,区别如下:
(1).el不要写,为什么?——最终所有的组件都要经过vm的管理,有vm中的el决定服务那个容器。
(2).data必须写成函数,为什么?——避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
如何使用组件?
1.局部注册:用new Vue的时候传入components选项。
2.全局注册:用Vue.component('组件名',组件)
编写组件标签:
<组件名><组件名/>
几个注意点:
1.关于组件名:
一个单词组成:首字母小写/大写
多个单词组成:
(kebab-case命名):my-school
CamelCase命名:MySchool(需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:<school></school>
第二种写法:<school/>
备注:不使用脚手架时,<school/>会导致后续组件不能渲染。
3.一个简写方式:
const school = Vue.extend(options) 可简写为:const school = options
VueComponent
关于VueComponent:
1.组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
2.我们只需要写<school></school>或<school/>,Vue解析时会帮我们创建school组件的实例对象。
即Vue帮我们执行的:new VueComponent(options)。
3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent。
4。关于this的指向:
(1).组件配置中,data函数、methods函数等等,它们的this均是【VueComponent实例对象】
(2).new Vue(options)配置中:data函数、methods函数等等,它们的this均是【Vue实例对象】。
5.Vue和VueComponent对比:
(1).一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
(2).为什么要有这个关系:让组件实例对象可以访问到Vue原型上的属性、方法。
关于不同版本的vue
1.vue.js 与 vue.runtime.xxx.js的区别:
(1).vue.js 是完整版的vue,包含:核心功能+模板解析器
(2).vue.runtime.xxx.js是运行版的vue,只包含核心功能,不包含模板解析器。
2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement取指定具体的内容。
vue.config.js可以进行定制化配置
ref属性
ref属性:
1.被用来给元素或子组件注册引用信息(id的替代者)
2.应用在HTML标签上获取的是真实dom元素,应用在组件标签上是组件实例对象。
3.使用方式:
打标识:<h1 ref="xxx"></h1> 或<School ref="xxx"></School>
获取:this.$refs.xxx
配置项props
功能:让组件接收外部传过来的数据
(1).传递数据:
<Demo name="xxx"></Demo>
(2).接收数据:
第一种方式(只接收):
props:['name']
第二种方式(限制类型):
props:{
name:Number
}
第三种方式(限制类型、限制必要性、指定默认值):
props:{
name:{
type:String,//类型
required:true,//必要性
default:'老王'//默认值
}
}
备注:props是只读的,Vue底层会监视你对props的修改,如果进行了修改,就会发出警告,若业务需求要求修改,那么请复制props的内容到data中,然后取修改data中的数据。
mixin(混入)
功能:可以把多个组件共用的配置提取成一个混入对象
使用方式:
第一步定义混入,例如:
{
data(){},
methods:{}
}
第二步使用混入,例如:
(1).全局混入:Vue.mixin(xxx)
(2).局部混入:mixins:['xxx']
插件
功能:用于增强vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件:
export default {
install(Vue){
}
}
//使用插件
import xxx from './'
Vue.use(xxx)
Storage
1.存储大小一般支持5M左右(不同浏览器可能还不同)
2.浏览器端通过window.sessionStorage和window.localStorage实现本地存储机制。
3.相关API:
setItem()、getItem()、removeItem()、clear()
组件的自定义事件
1.一种组件间通信的方式,适用于:子组件==》父组件
2.使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
3.绑定自定义事件:
(1).第一种方式,在父组件中:<Demo @test="test"></Demo>或<Demo v-on:test="test"></Demo>
(2).第二种方式,在父组件中:
<Demo ref="test"></Demo>
mounted(){
this.refs.xxx.$on('test',this.test())
}
(3).若想自定义事件只能触发一次,可以使用once修饰符,或$once方法。
4.触发自定义事件:this.$emit('test',数据)
5.解绑自定义事件:this.$off('test')
6.组件也可以绑定原生DOM事件,需要使用native修饰符。
7.注意:通过this.$refs.xxx.$on('test',回调函数)绑定事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出现问题!
全局事件总线
1.一种组件间通信的方式,适用于任意组件间通信。
2.安装全局事件总线:
new Vue({
beforeCreate(){
Vue.prototype.$bus = this
}
})
3.使用事件总线:
(1).接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods:{
demo(){}
}
mounted(){
this.$bus.$on('xxx',this.demo)
}
(2).提供数据:this.$bus.$emit('xxx',数据)
4.最好在beforeDestroy钩子中,用$off去解绑当前组件用到的事件。
消息订阅与发布(pubsub)
1.一种组件间通信的方式,适用于任意组件间通信。
2.使用步骤:
(1).安装pubsub:npm i pubsub-js
(2).引入:import pubsub from 'pubsub-js'
(3).接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
methods(){
demo(data){}
}
mounted(){
this.pid = pubsub.subscribe('xxx',this.demo)//订阅消息
}
3.提供数据:pubsub.publish('xxx',数据)
5.最好在beforeDestroy钩子中,用pubsub.unsubscribe(pid)去取消订阅。
vue脚手架配置代理
方法一:
在vue.config.js中添加如下配置:
devServer:{
proxy:"http://localhost:5000"
}
说明:
1.优点:配置简单,请求资源是直接发给前端即可。
2.缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
3.工作方式:如果按照上述配置,当请求了前端不存在的资源时,才将请求转发给服务器。(优先匹配前端资源)
方法二:
编写vue.config.js配置具体代理规则:
devServer:{
proxy:{
'/api':{
target:'',
changeOrigin:true,
pathRewrite:{'^/api':''}
}
}
}
changeOrigin默认值为true,是否改变服务器请求头中的host。
说明:
1.可以配置多个代理,可以灵活的控制请求是否走代理。
2.缺点:配置略微繁琐,请求资源时必须要加前缀。
插槽
1.作用:让父组件可以向子组件指定位置插入HTML结构,也是一种组件间通信的方式,适用于父组件==》子组件。
2.分类:默认插槽、具名插槽、作用域插槽
3.使用方式:
(1).默认插槽:
父组件中:
<Demo>
<div>
html结构
</div>
</Demo>
子组件中:
<template>
<div>
<slot>默认内容</slot>
</div>
</template>
(2).具名插槽:
父组件中:
<Demo>
<template slot="center"></template>
<template v-slot:center></template>
</Demo>
子组件中:
<template>
<div>
<slot name="center">默认内容</slot>
</div>
</template>
(3).作用域插槽:
1.理解:数据在组件的自身,但数据生成的结构需要组件的使用者来决定。
2.具体代码:
父组件中:
<Demo>
<template scope="scopeData"></template>
<template slot-scope="scopeData"></template>
</Demo>
子组件中:
<template>
<div>
<slot :data="data">默认内容</slot>
</div>
</template>