uniapp组件传值(props)
类别
- vue组件(日常建议使用)
- 小程序自定义组件(小程序规范)
一个.vue文件就是一个组件
定义组件名规范
- kebab-case(短横线分隔命名)
- PascalCase(首字母大写命名)
自定义组件
- 新建components目录
- components新建组件
- 组件编写代码
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">标题</text>
</view>
</view>
</template>
- 首页使用组件
<template>
<!-- 使用组件 -->
<!-- 可以在不用页面重复使用 -->
<view>
<my-component></my-component>
</view>
</template>
props
存放数组或对象,接收来自父组件的数据
选项 | 类型 | 说明 |
---|---|---|
type | String 、 Number 、 Boolean 、 Array 、 Object 、 Date 、 Function 、 Symbol ,任何自定义构造函数、或上述内容组成的数组 | 会检查一个 prop 是否是给定的类型,否则抛出警告 |
default | any | 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。 |
required | Boolean | 定义该 prop 是否是必填项 |
validator | Function | 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 false 的值 (也就是验证失败),一个控制台警告将会被抛出 |
- 静态传值-父传子
- 子(组件)
<template>
<view class="content">
<!-- 因为imgurl是会变化的 所以加: 使用的是v-bind -->
<image class="logo" :src="imgurl"></image>
<view class="text-area">
<text class="title">标题</text>
</view>
</view>
</template>
<script>
export default {
name:"my-component",
props:["title","imgurl"],
data() {
return {
};
}
}
</script>
- 父(index)
<template>
<!-- 使用组件 -->
<view>
<my-component title="首页" imgurl="/static/logo.png"></my-component>
</view>
</template>
- 动态传值-父传子
- 父(index)
<template>
<!-- 使用组件 -->
<!-- 等号后面的值在data中定义 -->
<view>
<my-component :title="tit" :imgurl="img"></my-component>
</view>
</template>
<script>
export default {
data() {
return {
tit: 'Hello',
img:'/static/logo.png'
}
},
onLoad() {
},
methods: {
}
}
</script>
- 默认值(不写属性时采用默认值)
- 子(my-component)
<script>
export default {
name:"my-component",
// props:["title","imgurl"],
props:{
title:{
type:String,
default:"默认值"
},
imgurl:{
type:String,
default:"/static/defaultimg.png"
}
},
data() {
return {
};
}
}
</script>
- 默认值-数组类型
<template>
<view class="content">
<image class="logo" :src="imgurl"></image>
<view class="text-area">
<text class="title">标题</text>
</view>
<view>{{list}}</view>
</view>
</template>
<script>
export default {
name:"my-component",
// props:["title","imgurl"],
props:{
list:{
type:Array,
default(){
return [1,2,3]
}
},
title:{
type:String,
default:"默认值"
},
imgurl:{
type:String,
default:"/static/defaultimg.png"
}
},
data() {
return {
};
}
}
</script>
- 默认值-对象类型
<template>
<view class="content">
<image class="logo" :src="imgurl"></image>
<view class="text-area">
<text class="title">标题</text>
</view>
<view>{{list}}</view>
<view>{{obj}}</view>
</view>
</template>
<script>
export default {
name:"my-component",
// props:["title","imgurl"],
props:{
obj:{
type:Object,
default(){
return {name:'lxy',age:'22'}
}
},
list:{
type:Array,
default(){
return [1,2,3]
}
},
title:{
type:String,
default:"默认值"
},
imgurl:{
type:String,
default:"/static/defaultimg.png"
}
},
data() {
return {
};
}
}
</script>
- 子组件向父组件传值
- myconponent
<template>
<view class="content">
<image class="logo" :src="imgurl"></image>
<view class="text-area">
<text class="title">标题</text>
</view>
<view>{{list}}</view>
<view>{{obj}}</view>
<view>
<!-- @blur失去焦点时会触发 -->
<input placeholder="请输入..." @blur="inputData" />
</view>
</view>
</template>
<script>
export default {
name: "my-component",
// props:["title","imgurl"],
props: {
obj: {
type: Object,
default () {
return {
name: 'lxy',
age: '22'
}
}
},
list: {
type: Array,
default () {
return [1, 2, 3]
}
},
title: {
type: String,
default: "默认值"
},
imgurl: {
type: String,
default: "/static/defaultimg.png"
}
},
data() {
return {
};
},
methods: {
// 要带参
inputData(e) {
// 自定义事件
//e.datail.value输入框要输入的内容
this.$emit("myevent", e.datail.value)
}
}
}
</script>
- index
<template>
<!-- 使用组件 -->
<view>
<view>展示子组件传回来的值:{{a}}</view>
<my-component :title="tit" :imgurl="img" @myevent="getChildData"></my-component>
</view>
</template>
<script>
export default {
data() {
return {
tit: 'Hello',
img: '/static/logo.png',
a: ''
}
},
onLoad() {
},
methods: {
getChildDate(e) {
this.a = e
}
}
}
</script>
- 点击事件
<template>
<view>
<my-component title="我的" @click.native="myclick"></my-component>
</view>
</template>
-
sync:当一个子组件改变了一个
prop
的值时,这个变化也会同步到父组件中所绑定。.sync
它会被扩展为一个自动更新父组件属性的v-on
监听器。- 在components文件下新建mysync
<template> <view> <view @click="changeTitle">{{title}}</view> </view> </template> <script> export default { data() { return { } }, props:{ title:{ default:"hello" } }, methods: { changeTitle(){ //触发一个更新事件 this.$emit('update:title',"uniapp") } } } </script>
- my.vue
<template>
<view>
<mysync :title.sync="title"></mysync>
</view>
</template>
<script>
export default {
data() {
return {
title:"hello vue.js"
}
},
methods: {
}
}
</script>
组件是有生命周期的
父子同步,为了简化
- updated()
//mysync.vue
<template>
<view>
<view @click="changeTitle">{{title}}</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
props:{
title:{
default:"hello"
}
},
//组件的生命周期:数据更新后会触发
updated(){
console.log(this.title)
},
methods: {
changeTitle(){
//触发一个更新事件
this.$emit('update:title',"uniapp")
}
}
}
</script>
- onHide()
<template>
<view>
<mysync :title.sync="title"></mysync>
</view>
</template>
<script>
export default {
data() {
return {
title:"hello vue.js"
}
},
onHide(){
console.log("父组件:"+this.title)
},
methods: {
}
}
</script>
菜单实例
使用组件实现菜单,左右滑动菜类并点击后切换菜品的功能
- 父组件(index.vue)
<template>
<view class="homeLayout ">
<!-- 自定义导航栏 -->
<view>
<uni-nav-bar title="舌尖上的中国" right-icon="search" background-color="#f7f7fa" height="65px" border="false"
shadow="true"></uni-nav-bar>
</view>
<!-- 轮播图 -->
<view class="banner">
<swiper circular indicator-dots indicator-color="rgba(255,255,255,0.5)" indicator-active-color="#fff"
autoplay>
<swiper-item v-for="item in bannerList" :key="item._id">
<image :src="item.picurl" mode="aspectFill"></image>
</swiper-item>
</swiper>
</view>
<!-- 公告 -->
<view class="notice">
<!-- 左侧图标 -->
<view class="left">
<uni-icons type="sound-filled" size="20" color="#28b389"></uni-icons>
<text class="text">公告</text>
</view>
<!-- 公告内容 -->
<view class="center">
<swiper vertical autoplay interval="1500" duration="300" circular>
<swiper-item v-for="item in noticeList" :key="item._id">
{{item.title}}
</swiper-item>
</swiper>
</view>
<!-- 右侧箭头 -->
<view class="right">
<uni-icons type="right" size="16" color="#333"></uni-icons>
</view>
</view>
<!-- 菜系展示 -->
<scroll-view class="menu-list" scroll-x="true">
<view class="menu-item" :class="{'active': item.id === activeId}" v-for="(item, index) in menuList"
:key="index" @click="handleMenuClick(item.id)">
{{ item.name }}
</view>
</scroll-view>
<!-- 菜品展示 -->
<view class="newsbox" v-for="(item,index) in menuList[activeId].list" :key="index">
<munebox :item="item" @click.native="godetail(item)"></munebox>
</view>
</view>
</template>
<script>
export default {
data() {
return {
activeId: 0, // 当前激活的菜单项ID
bannerList: [{
_id: 0,
picurl: '/static/banner1.jpg',
}, {
_id: 1,
picurl: '/static/banner2.jpg',
}, {
_id: 2,
picurl: '/static/banner3.jpg',
}, ],
noticeList: [{
_id: 0,
title: '东坡肉的由来',
}, {
_id: 1,
title: '蘑菇是否有毒,如何判断',
}, {
_id: 2,
title: '紫甘蓝的营养价值',
}, ],
menuList: [ // 菜单列表数据
{
id: 0,
name: ' 鲁菜',
list: [{
cname: '爆双脆',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/bsc.jpg',
detail: '油爆双脆属鲁菜,是山东地区特色传统名菜,发源于山东济南。烹饪以爆菜油爆为主油。正宗的油爆双脆的做法极难,对火候的要求极为苛刻,欠一秒钟则不熟,过一秒钟则不脆,是中餐里制作难度最大的菜肴之一。色、香、味、形兼备的特色美食。在袁枚的《随园食单》和梁实秋的《雅舍谈吃》中对此菜均有高度赞誉。'
},
{
cname: '葱烧海参',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/cshs.jpg',
detail: '这道菜以水发海参和大葱为主要原料,海参清鲜、柔软香滑,葱段香浓,食后无余汁,是“古今八珍”之一,营养丰富,滋肺补肾。'
},
]
}, {
id: 1,
name: '晋菜',
list: [{
cname: '过油肉',
pageview: 915,
uploader: '王琳',
imgurl: '../../static/gyr.jpg',
detail: '过油肉是山西省最著名的传统菜肴,历经代代厨师精心烹制相传至今。号称“三晋一味”,其起源有多种说法,各地的做法也不一,较著名的有大同、太原、阳泉、晋城的过油肉,晋城的“大米过油肉”,特色是多汤水,搭配刚出锅的大米饭一起吃堪称一绝。'
},
{
cname: '大同刀削面',
pageview: 913,
uploader: '李旺',
imgurl: '../../static/dtdxm.jpeg',
detail: '大同刀削面是山西省大同市的一道传统小吃,属于山西面食;该菜品入口外滑内筋,软而不粘,越嚼越香。山西大同的刀削面之所以独树一帜,主要与它的做工有关系。'
},
]
}, {
id: 2,
name: '川菜',
list: [{
cname: '宫保鸡丁',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/gbjd.jpeg',
detail: '宫保鸡丁的特色是辣中有甜,甜中有辣,鸡肉的鲜嫩配合花生的香脆,入口鲜辣酥香,红而不辣,辣而不猛,肉质滑脆。'
},
{
cname: '麻婆豆腐',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/mpdf.jpeg',
detail: '麻婆豆腐,是四川地区传统名菜之一,属于川菜,主料为:豆腐,辅料为:蒜苗、牛肉沫(其他肉也可以),调料为:豆瓣、辣椒面和花椒面、酱油、生抽、老抽、糖、淀粉等,麻来自花椒,辣来自辣椒面,此菜成菜麻、辣、鲜、香、烫、整、嫩、酥,突出川菜麻辣味型的特点。此外,麻婆豆腐还传到了美国、加拿大、英国、法国、越南、新加坡、马来西亚、日本、澳大利亚等国,成了国际名菜。'
},
{
cname: '鱼香肉丝',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/yxrs.jpg',
detail: '鱼香肉丝,是四川的一道特色名菜,该菜品以泡辣椒、泡姜、大蒜、黄葱、生姜和醋炒制猪里脊肉丝而成,由民国时期的一位川菜大厨所创制,相传灵感来自泡椒肉丝。'
}
]
}, {
id: 3,
name: '粤菜',
list: [{
cname: '白切鸡',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/bqj.jpeg',
detail: '白斩鸡又叫白切鸡、三黄油鸡,是一道中华民族特色菜肴,起源于广东 [11],是一道经典的粤菜 [5],在南方菜系中普遍存在,如广府菜 [10]、上海菜 [12]、客家菜(广东 [7]、福建 [8]、江西 [16]、广西 [13])中都有 [7]、始于清代的民间酒店,因烹鸡时不加调味白煮而成,食用时随吃随斩,故称“白斩鸡”。'
},
{
cname: '烧鹅',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/se.jpg',
detail: '鹅以乌鬃鹅为优,去翼、脚、内脏的整鹅,吹气,涂五香料,缝肚,滚水烫皮,过冷水,糖水匀皮,晾风而后腌制,最后挂在烤炉里或明火上转动烤成,斩件上碟,便可进食。'
},
]
}, {
id: 4,
name: '苏菜',
list: [{
cname: '狮子头',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/szt.jpeg',
detail: '狮子头,原名葵花斩肉、葵花肉丸,是中国淮扬菜系中的一道传统菜肴。始于隋朝,传说是在隋炀帝游幸时,厨师以扬州万松山、金钱墩、象牙林、葵花岗四大名景为主题做成了松鼠桂鱼、金钱虾饼、象牙鸡条和葵花斩肉四道菜,唐代时改名为狮子头。此菜口感软糯滑腻,健康营养。'
},
{
cname: '黄泥煨鸡',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/hnwj.jpeg',
detail: '叫花鸡又称常熟叫化鸡、煨鸡,是江苏省常熟市的一道传统名菜,它的做法是先给处理好鸡刷上料汁,再用荷叶、猪网油及黄泥土层层包裹,最后丢进柴火堆中煨熟。'
},
]
}, {
id: 5,
name: '浙菜',
list: [{
cname: '龙井虾仁',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/ljxr.jpg',
detail: '龙井虾仁将茶饮与虾仁融合,整体清新软嫩,虾仁玉白,鲜嫩,芽叶清香,色泽雅丽,虾中有茶香,茶中有虾鲜,食后清口开胃,回味无穷'
},
{
cname: '冰糖甲鱼',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/btjy.jpeg',
detail: '冰糖甲鱼是一道以甲鱼为主料,酱油、小葱、冰糖、姜等为辅料,炖煮而成的药膳,具有滋阴调理、补血调理、补虚养身调理、营养不良调理功效。'
},
]
}, {
id: 6,
name: '湘菜',
list: [{
cname: '剁椒鱼头',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/djyt.jpeg',
detail: '剁椒鱼头(英文名:Chop bell pepper fish head)是湖南省的传统名菜,属于湘菜系。据传,起源和清代文人黄宗宪有关。通常以鳙鱼鱼头、剁椒为主料,配以豉油、姜、葱、蒜等辅料蒸制而成。菜品色泽红亮、味浓、肉质细嫩。肥而不腻、口感软糯、鲜辣适口。'
},
{
cname: '发丝牛百叶',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/fsnby.jpeg',
detail: '发丝百叶又名发丝牛百叶,始创于19世纪20年代,是一道湖南名菜。发丝百叶以牛百叶切丝急火爆炒而成。成菜后,色泽白净,形如发丝,质地脆嫩,集咸、鲜、辣、酸于一体。'
},
]
}, {
id: 7,
name: '徽菜',
list: [{
cname: '火腿炖甲鱼',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/htdjy.jpg',
detail: '火腿炖甲鱼属于徽菜,主要原料是甲鱼、火腿,口味是鲜香,工艺是炖,烹饪难度属于高级。甲鱼有较好的净血作用,常食者可降低血胆固醇,因而对高血压、冠心病患者有益;甲鱼还能“补劳伤,壮阳气,大补阴之不足”;对肺结核、贫血、体质虚弱等多种病患亦有一定的辅助疗效'
},
{
cname: '黄山炖鸽',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/hsdg.jpeg',
detail: '黄山炖鸽是安徽黄山特色传统名菜,取黄山菜鸽与黄山山药隔水炖制而成。汤清味鲜,鸽肉酥烂,山药清香爽口。此菜鸽肉滋味鲜美,营养丰富,易于消化,有补脑健肾、增强记忆力的食疗功效。山药肉松软细腻,略甜,富含淀粉,常被人们视作为滋补蔬菜食用。此菜又是一道滋补健身的佳肴。'
},
]
}, {
id: 8,
name: '闽菜',
list: [{
cname: '佛跳墙',
pageview: 975,
uploader: '张琳',
imgurl: '../../static/ftq.jpg',
detail: '佛跳墙又名福寿全,是福建省福州市的一道特色名菜,属闽菜系。相传,该菜品是在清道光年间由福州聚春园菜馆老板郑春发研制出来的,又据费孝通先生记,发明此菜者乃一帮要饭的乞丐。'
},
{
cname: '鸡汤汆海蚌',
pageview: 93,
uploader: '张琳',
imgurl: '../../static/jtchb.jpeg',
detail: '鸡汤汆海蚌是一道福建的特色名菜,属于闽菜系-福州菜。是福州地区传统宴席上必备的一道汤菜。使用漳港海蚌、鸡肉作为主料,配以牛肉、猪里脊肉等辅料制作而成的美食。以鲜活海蚌为原料,氽以滚热的鸡汤而成,口味咸鲜味。'
},
]
}
]
};
},
methods: {
handleMenuClick(id) {
this.activeId = id; // 更新当前激活的菜单项ID // 这里可以添加其他逻辑,比如发起网络请求等
},
godetail(item) {
var objStr = JSON.stringify(item);
uni.navigateTo({
url: "/pages/detail/detail?it=" + encodeURIComponent(objStr)
})
}
}
}
</script>
<style lang="scss" scoped>
.homeLayout {
.banner {
//轮播图的样式
width: 750rpx;
padding: 30rpx 0;
swiper {
width: 750rpx;
height: 340rpx;
&-item {
//讨论&-item的含义
width: 100%;
height: 100%;
padding: 0 30rpx;
image {
width: 100%;
height: 100%;
border-radius: 20rpx;
}
}
}
}
//公告的样式
.notice {
width: 690rpx;
height: 80rpx;
line-height: 80rpx;
background: #f9f9f9;
margin: 0 auto;
border-radius: 80rpx;
display: flex;
.left {
width: 140rpx;
display: flex;
align-items: center;
justify-content: center;
.text {
color: #28b389;
font-weight: 600;
font-size: 28rpx;
}
}
.center {
flex: 1;
swiper {
height: 100%;
&-item {
height: 100%;
font-size: 30rpx;
color: #666;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
.right {
width: 70rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
// 横向菜单样式
.menu-list {
box-sizing: border-box;
height: 120rpx;
padding-left: 30rpx;
padding-right: 30rpx;
white-space: nowrap; //不换行
// 去除h5端scroll-view的滚动条
/deep/ ::-webkit-scrollbar {
width: 4px !important; //使用一个 !important 规则时,此声明将覆盖任何其他声明
height: 1px !important;
overflow: auto !important;
background: transparent !important;
display: block;
}
.menu-item {
font-size: 40rpx;
display: inline-block; //水平排列
line-height: 75rpx;
padding: 0 30rpx;
margin: 20rpx 0;
border-radius: 60rpx;
}
.menu-item.active {
color: #fff;
background-color: #007bff;
}
}
// 菜品展示样式
.newsbox {
display: flex;
box-sizing: border-box;
padding-left: 30rpx;
padding-right: 30rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f9f9f9;
.pic {
width: 230rpx;
height: 100rpx;
image {
width: 100%;
height: 100%;
}
}
.text {
flex: 1;
padding-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.title {
font-size: 38rpx;
color: #333;
}
.info {
font-size: 26rpx;
color: #999;
text {
padding-right: 30rpx;
}
}
}
}
}
</style>
- 子组件(menubox.vue)
<template>
<view>
<!-- 菜品展示 -->
<view class="menubox" v-for="(item,index) in menuList[activeId].list" :key="index">
<view class="pic">
<image :src="item.imgurl" mode="aspectFill">
</view>
<view class="text">
<view class="title">{{item.cname}}</view>
<view class="info">
<text>{{item.uploader}}</text>
<text>{{item.pageview}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "menubox",
props: {
item: {
type: Object,
default () {
return {
cname: '默认值',
pageview: 0,
uploader: '无名氏',
imgurl: '../../static/bsc.jpg'
}
}
}
},
data() {
return {
};
},
}
</script>
<style lang="scss">
// 菜品展示样式
.menubox {
display: flex;
box-sizing: border-box;
padding-left: 30rpx;
padding-right: 30rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f9f9f9;
.pic {
width: 230rpx;
height: 100rpx;
image {
width: 100%;
height: 100%;
}
}
.text {
flex: 1;
padding-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.title {
font-size: 38rpx;
color: #333;
}
.info {
font-size: 26rpx;
color: #999;
text {
padding-right: 30rpx;
}
}
}
}
</style>
- 新建detail页面
<template>
<view>
<!-- 自定义导航栏 -->
<!-- shadow:导航栏下是否有阴影 -->
<view>
<uni-nav-bar title="舌尖上的中国" right-icon="search" background-color="#f7f7fa" height="65px" border="false"
shadow="true"></uni-nav-bar>
</view>
<view class="ALL">
<view class="pic">
<image :src="detail.imgurl" mode="aspectFill"></image>
</view>
<view class="name">
{{detail.cname}}
</view>
<view class="upload">
{{detail.uploader}}
|
{{detail.pageview}}
</view>
<view class="detail">
{{detail.detail}}
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
//反序列化
detail: {}
}
},
//options存储上个页面传过来的参数
onLoad(options) {
this.detail = JSON.parse(decodeURIComponent(options.it))
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.ALL {
// display: flex;
width: 100%;
height: auto;
// background-color: #ebebeb;
.pic {
width: 700rpx;
height: 500rpx;
align-items: center;
justify-items: center;
margin-left: 11px;
image {
width: 100%;
height: 100%;
}
}
.name {
color: #ff7c40;
font-weight: bold;
font-size: 28px;
text-align: center;
margin-top: 10px;
}
.detail {
overflow: hidden;
text-overflow: ellipsis;
text-indent: 2em;
color: #757575;
margin-top: 10px;
letter-spacing: 1px;
}
.upload {
text-align: center;
margin-top: 10px;
margin-bottom: 10px;
color: #b5b5b5;
font-weight: bold;
}
}
</style>
最终成果
easycom组件规范
特点:
-
直接在view中使用
-
自启
-
组件安装在项目的components目录下或uni_modules目录
-
符合components/组件名称/组件名称.(vue|uvue)目录结构
easycom
是自动开启的,不需要手动开启,有需求时可以在pages.json
的easycom
节点进行个性化设置,如关闭自动扫描,或自定义扫描匹配组件的策略。设置参数如下:
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
autoscan | Boolean | true | 是否开启自动扫描,开启后将会自动扫描符合components/组件名称/组件名称.vue 目录结构的组件 |
custom | Object | - | 以正则方式自定义组件匹配规则。如果autoscan 不能满足需求,可以使用custom 自定义匹配规则 |