自定义组件
新建在/components/组件名.vue文件
组件文档结构
<template><view>......</view>
</template>
<script>export default {name: "组件名称",//属性自定义props: {属性名称: {type: String, //属性类型value: "值"},......},//组件生命周期created: function(e) {},methods: {函数名称: function(obj) {},}}
</script>
<style>组件样式
</style>
使用组件
1、引用组件
import 组件名称 from "../../components/组件名.vue";
2、注册组件
export default{components:{组件名称},
}
3、在试图模板中使用组件
<组件名称 组件属性="对应的值"></组件名称>
全局注册
和vue
一样的方式去配置全局组件,需在main.js
里进行全局注册,注册后就可在所有页面里使用该组件。
1、main.js
里进行全局导入和注册
import Vue from 'vue'
import pageCafe from './components/page-cafe.vue'
Vue.component('page-cafe',pageCafe)
2、index.vue
里可直接使用组件
<template><view><page-cafe></page-cafe></view>
</template>
局部注册
1、传统vue
规范:在index.vue
页面中,通过import
方式引入组件 ,在components
选项中定义你想要使用的组件。
<!-- 在index.vue引入 uni-badge 组件-->
<template><view><uni-badge text="1"></uni-badge></view>
</template>
<script>import uniBadge from '@/components/uni-badge/uni-badge.vue';export default {components: {uniBadge}}
</script>
对于components对象中的每个property来说,其property名就是自定义元素的名字,其property值就是这个组件的选项对象。
在对象中放一个类似uniBadge的变量名其实是缩写,即这个变量名同时是:
- 用在模板中的自定义元素的名称
- 包含了这个组件选项的变量名(仅支持驼峰法命名)
2、通过uni-app
的easycom
将组件引入精简为一步。只要组件安装在项目的components目录下,并符合components/组件名称/组件名称.vue目录结构。就可以不用引用、注册,直接在页面中使用。
<template><view><uni-badge text="1"></uni-badge></view>
</template>
<script>// 这里不用import引入,也不需要在components内注册uni-badge组件。template里就可以直接用export default {data() {return {}}}
</script>
- easycom是自动开启的,不需要手动开启,有需求时可以在pages.json的easycom节点进行个性化设置
- 不管components目录下安装了多少组件,easycom打包后会自动剔除没有使用的组件,对组件库的使用尤为友好
props
props可以是数组或对象,用于接收来自父组件的数据。props可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。
选项 | 类型 | 说明 |
---|---|---|
type | String、Number、Boolean、Array、Object、Date、Function、Symbol,任何自定义构造函数、或上述内容组成的数组 | 会检查一个 prop 是否是给定的类型,否则抛出警告 |
default | any | 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回 |
required | Boolean | 定义该 prop 是否是必填项 |
validator | Function | 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 false 的值 (也就是验证失败),一个控制台警告将会被抛出 |
示例:子组件定义
<template><view><view>{{age}}</view></view>
</template>
<script>export default {props: {// 检测类型 + 其他验证age: {type: Number,default: 0,required: true,validator: function(value) {return value >= 0}}}}
</script>
示例:父组件传递age
属性
<template>
<view><componentA :age="10"></componentA>
</view>
</template>
组件之间的数据传输
组件之间的数据传输,以及事件传递是比较常见的一个应用
事件注册/触发方式
客户端调用组件的时候,注册事件。组件触发注册的事件,达到向父组件传值的目的
子组件free-cafe.vue
<template><!-- <button type="default" @tap="$emit('openExtend')">{{title}}</button> --><button type="default" @tap="handleJs">{{title}}</button>
</template><script>export default {name: "freeCa",props: {title: String,default: ''},methods: {handleJs() {this.$emit('openExtend', { name: 'cafe', 'sex': '男' })}}}
</script>
父组件调用时注册事件
<template><view><free-cafe :title="title" @openExtend="openExtend"></free-caafe></view>
</template>
<script>import freeCafe from '../../components/free-cafe.vue'export default {components: {freeCafe},data() {return {title: 'haha'}},methods: {openExtend(obj) {console.log(obj)}}}
</script>
客户端调用组建引用方式
客户端为调用的组件设置引用别名,就可以调用其方法进行传值
子组件free-cafe.vue
<template><button type="default">{{title}}</button>
</template><script>export default {name: "freeTs",props: {title: String,default: ''},methods: {seeme(obj) {console.log(obj)}}}
</script>
父组件为组建设置引用别名,就可以调用其方法进行传值
<template><view><free-cafe :title="title" ref="free"></free-test><button type="default" @tap="seeData">test</button></view>
</template>
<script>import freeCafe from '../../components/free-cafe.vue'export default {components: {freeCafe},data() {return {title: 'haha'}},methods: {seeData() {this.$refs.free.seeme({ title: '6666', created_at: '2020-09-19' });}}}
</script>
ref
被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的$refs
对象上。
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:
<!-- 非H5端不支持通过this.$refs.content来获取view实例 -->
<view ref="content">hello</view><!-- 支持通过this.$refs.child来获取child-component实例 -->
<child-component ref="child"></child-component>
尽管存在prop和事件,有的时候你仍可能需要在JavaScript里直接访问一个子组件。访问子组件实例或子元素,通过ref为子组件赋予一个ID引用,在vue的js中可通过this.$refs.XXX来获取到组件对象。
<base-input ref="usernameInput"></base-input>
你已经定义了这个ref的组件里,你可以使用this.$refs.usernameInpu
t来访问这个实例
<!-- base-input子组件页面 -->
<template><view><input :focus="isFocus" type="text" placeholder="请输入内容" /></view>
</template>
<script>export default {name: "base-input",data() {return {"isFocus": false};},methods: {focus() {this.isFocus = true}}}
</script>
允许父级组件通过下面的代码聚焦里的输入框
<!-- index 父组件页面 -->
<template><view><base-input ref="usernameInput"></base-input><button type="default" @click="getFocus">获取焦点</button></view>
</template>
<script>export default {methods: {getFocus() {// 通过组件定义的ref调用focus方法this.$refs.usernameInput.focus()}}}
</script>
注意
非H5端只能用于获取自定义组件,不能用于获取内置组件实例(如:view、text)
自定义事件
你可能有很多次想要在一个组件的根元素上直接监听一个原生事件。 这时,你可以使用 @ 事件的.native
修饰符
- 注意:在app、小程序端和h5端表现不一致,h5端获取到的是浏览器原生事件。
<template><view><!-- 我是父组件 --><componentA @click.native="clickComponentA" style="height: 200px;"></componentA></view>
</template>
<script>export default {methods: {clickComponentA() {console.log("clickComponentA");}}}
</script>
<template><view><!-- 我是子组件 --><view type="default" @click.stop="open" style="height: 30px;">点击</view></view>
</template>
<script>export default {methods: {open() {console.log("open");}}}
</script>
.sync 修饰符
当一个子组件改变了一个prop的值时,这个变化也会同步到父组件中所绑定。.sync它会被扩展为一个自动更新父组件属性的v-on监听器。
<!-- 父组件 -->
<template><view><syncA :title.sync="title"></syncA></view>
</template>
<script>export default {data() {return {title: "hello vue.js"}}}
</script>
<!-- 子组件 -->
<template><view><view @click="changeTitle">{{title}}</view></view>
</template>
<script>export default {props: {title: {default: "hello"},},methods: {changeTitle() {// 触发一个更新事件this.$emit('update:title', "cafe-app")}}}
</script>
命名限制
在uni-app
中以下这些作为保留关键字,不可作为组件名。
a、canvas、cell、content、countdown、datepicker、div、element、embed、header、image、img、indicator、input、link、list、loading-indicator、loading、marquee、meta、refresh、richtext、script、scrollable、scroller、select、slider-neighbor、slider、slot、span、spinner、style、svg、switch、tabbar、tabheader、template、text、textarea、timepicker、transition-group、transition、video、view、web
注意
除以上列表中的名称外,标准的 HTML 及 SVG 标签名也不能作为组件名。
在百度小程序中使用时,不要在 data 内使用 hidden ,可能会导致渲染错误。
methods中不可使用与生命周期同名的方法名。