组件通信
Vue组件间的通信方式(多种场景,通俗易懂,建议收藏)_vue实例 与vue实例通信-CSDN博客
通过props和events在父子组件之间进行通信。
Props Props
是父组件传递给子组件的数据。在Vue.js中,父组件可以通过子组件的标签属性传递数据给子组件。 在这段代码中的示例:
<mb-b-type-tabs :items="types" :value="model.type" @selected="onTypeSelected"/>
- :items="types" 和 :value="model.type" 是父组件传递给 mb-b-type-tabs 子组件的props。types 是一个包含账单类型的数组,model.type 是当前选中的账单类型。
- :items="types" 表示账单类型列表,子组件可以使用这个列表渲染选项。
- :value="model.type" 表示当前选中的账单类型,子组件可以根据这个值来设置当前选中的选项。
Events
子组件可以通过触发事件来通知父组件某些操作,父组件可以监听这些事件并做出响应。在这段代码中的实例:
<mb-b-type-tabs :items="types" :value="model.type" @selected="onTypeSelected"/>
- @selected="onTypeSelected" 是子组件触发的事件,父组件通过 onTypeSelected 方法来监听这个事件。
- 当用户在子组件中选择一个账单类型时,子组件会触发 selected 事件,并传递选中的账单类型数据。
- 父组件中的 onTypeSelected 方法会被调用,并接收到这个数据,然后更新父组件的状态。
代码中的事件处理方法:
methods: {
onTypeSelected(type) {
this.model.type = type.id;
// 可以在这里添加更多的逻辑,比如获取分类信息
this.getCategoryGroups();
},
}
- onTypeSelected 方法是父组件用来处理子组件触发的 selected 事件的方法。
- 当事件触发时,这个方法会被调用,并且接收到子组件传递的 type 对象。
- 在这个方法中,父组件更新了 model.type 的值,并调用 getCategoryGroups 方法来获取与新选中的账单类型相关的分类信息。
响应式设计
通过媒体查询和视窗单位(如rpx)来实现不同屏幕尺寸的适配。详细分析一下这段代码的这部分。
视窗单位(rpx
)
rpx
(responsive pixel)是一种在小程序中使用的视窗单位,它可以根据屏幕宽度进行自适应。在小程序中,屏幕宽度默认为750rpx。这意味着,如果屏幕宽度发生变化,rpx
单位的值也会相应地进行缩放,从而实现响应式布局。
代码示例:
.header {
padding: 35rpx 20rpx;
...
}
在这个例子中,.header
的 padding
使用了 rpx
单位,这意味着内边距会随着屏幕宽度的变化而缩放。
动态计算元素高度
在这段代码中,通过动态计算元素的高度来适应不同设备的屏幕尺寸。这是通过在组件的 onReady
生命周期钩子中使用 uni.getSystemInfo
和 uni.createSelectorQuery
来实现的。
代码示例:
dynamicHeight() {
let that = this;
uni.getSystemInfo({
success(res) {
let pH = res.windowHeight;
let query = uni.createSelectorQuery().in(that);
query.select("#edit-header").fields({ size: true });
query.select("#edit-amount").fields({ size: true });
query.select("#edit-key-board-container").fields({ size: true });
try{
query.exec((data) => {
data.map((i) => {
that.scrollHeight += i.height;
});
that.scrollHeight = pH - that.scrollHeight;
});
}
catch(err){
that.scrollHeight = pH - 210;
}
},
});
}
uni.getSystemInfo
获取设备的系统信息,包括屏幕的高度(windowHeight
)。uni.createSelectorQuery
用于获取页面中元素的尺寸信息。- 通过选择特定的元素(如
#edit-header
、#edit-amount
和#edit-key-board-container
),并获取它们的高度,然后计算出剩余的屏幕空间,从而动态设置scrollHeight
的值。 - 这种方法确保了即使在不同尺寸的屏幕上,内容区域的高度也能适应屏幕的变化。
通过使用视窗单位(如 rpx
)、动态计算元素高度以及媒体查询(如果需要),这段代码实现了响应式设计,确保了在不同设备上的兼容性和用户体验。这些技术使得布局能够自适应不同的屏幕尺寸,从而提供一致的界面和交互体验。
优化拓展:媒体查询
虽然这段代码中没有直接使用CSS媒体查询,但在Vue或小程序中,媒体查询仍然是一种常用的响应式设计技术。媒体查询允许开发者根据不同的屏幕尺寸、分辨率或其他特性来应用不同的CSS样式。示例:
@media screen and (max-width: 600px) {
.header {
padding: 20rpx;
}
}
这个媒体查询规则表示,当屏幕宽度小于或等于600px时,.header
的内边距将变为 20rpx
。
媒体查询入门指南 - 学习 Web 开发 | MDN (mozilla.org)
API交互
如何通过API请求获取数据(如获取账单分类、账户信息等),以及如何处理API响应。
获取账单分类 (getCategoryGroups
方法)
getCategoryGroups() {
if(this.model.type == undefined) return;
this.$api.getCategoryGroups({ type: this.model.type }).then((res) => {
if (res.data.code === 0) {
// this.categoryGroups = res.data.result.list;
this.categoryGroups = regroups(res.data.result);
}
});
},
- API请求:
getCategoryGroups
方法通过this.$api
发送一个请求到后端API,请求账单分类数据。请求中包含一个参数{ type: this.model.type }
,这是用于区分不同类型账单的分类。 - 处理响应: 使用
.then()
方法来处理Promise对象,它在API请求成功返回后被调用。检查响应中的code
字段是否为0(通常表示成功),然后使用regroups
函数处理分类数据,并将其赋值给this.categoryGroups
。
获取账单账户 (getAssetGroups
方法)
getAssetGroups() {
this.$api.getAssetGroups().then((res) => {
if (res.data.code === 0) {
// this.assetGroups = res.data.result.list;
this.assetGroups = regroups(res.data.result);
}
});
},
- API请求:
getAssetGroups
方法发送一个请求到后端API,获取账单账户信息。这个方法没有额外的参数,因为它获取所有账户信息。 - 处理响应: 同样使用
.then()
方法来处理成功的响应。检查code
字段,然后使用regroups
函数处理账户数据,并将其赋值给this.assetGroups
。
获取预购分组详情 (getPreOrderGroup
方法)
getPreOrderGroup(id) {
this.$api.getPreOrderGroupWithAmount({ id: id }).then((res) => {
if (res.data.code === 0) {
let result = res.data.result;
this.model.type = 0;
this.model.description = result.description;
this.model.amount = result.realAmount;
this.initAmount = result.realAmount;
this.group = result;
this.getLocation(); // 更新地址信息
} else {
this.$tip.toast(res.data.message);
this.isOrder = false;
}
});
},
- API请求:
getPreOrderGroup
方法通过this.$api
发送一个请求,获取与特定ID关联的预购分组的详情。 - 处理响应: 检查响应中的
code
字段。如果请求成功,更新模型(this.model
)的多个属性,如类型、描述和金额。如果请求失败,显示错误消息并更新isOrder
状态。
获取账单详情 (getBillDetail
方法)
getBillDetail(id, isCopy = false) {
this.$api.billDetail({ id: id }).then((res) => {
if (res.data.code === 0) {
let result = res.data.result;
this.model = result;
this.initAmount = result.amount;
if (isCopy) {
this.model.id = 0;
this.getLocation(); // 更新地址信息
} else {
let dateTime = new Date(result.time);
this.date = datetime.getCurDate(dateTime);
this.model.time = this.model.time.substring(11,16);
}
}
});
},
- API请求:
getBillDetail
方法发送一个请求,根据账单ID获取账单的详细信息。 - 处理响应: 检查
code
字段。如果请求成功,更新this.model
的状态,包括账单的ID、描述、金额等。如果请求是复制操作(isCopy
为true
),则重置ID并更新地址信息。
总结
在这些API交互中,我们可以看到以下模式:
- 请求发送: 使用
this.$api
对象发送请求,通常包含一些参数。 - 响应处理: 使用
.then()
方法来处理成功的响应,检查code
字段来确定请求是否成功,并更新组件的状态。 - 错误处理: 如果响应中的
code
字段表示错误,通常会显示一个提示消息,并可能更新一些状态来反映错误。
这种模式确保了组件能够与后端服务进行有效的数据交换,并根据响应更新用户界面。
代码分析示例
账单类型选择
在代码中,账单类型选择是通过一个名为 mb-b-type-tabs
的自定义组件实现的。这个组件允许用户从预定义的账单类型中选择一个。以下是对这部分代码的详细分析:
组件定义
在 <template> 部分,mb-b-type-tabs 组件被用来显示和选择账单类型:
组件定义
在 <template>
部分,mb-b-type-tabs
组件被用来显示和选择账单类型:
<view class="type-content">
<mb-b-type-tabs :items="types" :value="model.type" @selected="onTypeSelected"/>
</view>
:items="types"
: 这是通过v-bind
传递给组件的 props,types
是一个数组,包含了所有可供选择的账单类型。每个类型可能包含一个id
和一个text
属性,以及一个selcolor
属性用于定义选中时的颜色。:value="model.type"
: 这也是一个 props,表示当前选中的账单类型。它绑定到组件的value
prop 上,用于显示哪个类型当前被选中。@selected="onTypeSelected"
: 这是一个事件监听器,用于监听组件发出的selected
事件。当用户选择一个类型时,组件会触发这个事件,并传递选中的类型数据。
数据模型
在 data
函数中,types
和 model.type
被定义如下:
data() {
return {
types: [
{ id: 0, text: "支出", selcolor: "#47A271" },
{ id: 1, text: "收入", selcolor: "#C24F50" },
],
model: {
type: 0,
// 其他属性...
},
// 其他数据...
};
}
types
: 这是一个数组,定义了两种账单类型:支出和收入。每个类型有一个唯一的id
,一个用于显示的text
,以及一个selcolor
属性,后者在UI中用于显示选中状态的颜色。model.type
: 这个属性用于存储当前选中的账单类型。初始值设置为0
,表示默认选中“支出”。
事件处理
在 methods
部分,定义了 onTypeSelected
方法来处理类型选择事件:
methods: {
onTypeSelected(type) {
this.model.type = type.id;
// 可能还需要在这里调用其他方法来处理类型变更后的逻辑
},
// 其他方法...
}
onTypeSelected(type)
: 这个方法在用户选择一个账单类型时被调用。它接收一个参数 type
,这是被选中的类型的数据对象。方法内部,它更新 this.model.type
为选中类型的 id
。这会触发视图的更新,因为 model.type
被用作组件的 value
prop。
日期和时间选择
在代码中,日期和时间选择是通过两个 picker
组件实现的,允许用户分别为账单选择日期和时间。以下是对这部分代码的详细分析:
日期选择器
<picker
class="date-picker"
mode="date"
@change="onDatePicker"
fields="day"
:value="date"
:end="pickerEnd"
>
<view class="x-ac date">
<text> {{ selectedDateText }}</text>
</view>
</picker>
- 组件:
picker
是一个内置的小程序组件,用于选择日期和时间。 mode="date"
: 这个属性设置选择器的模式为日期选择。@change="onDatePicker"
: 这是一个事件监听器,当用户选择一个日期时触发onDatePicker
方法。fields="day"
: 这个属性限制日期选择器只能选择到天。:value="date"
: 这是一个绑定属性,表示当前选择的日期,它绑定到组件的value
prop 上。:end="pickerEnd"
: 这个属性设置日期选择器的最大日期,通常设置为当前日期以防止用户选择未来的日期。
时间选择器
<picker
class="time-picker"
mode="time"
@change="onTimePicker"
:value="model.time"
>
<view class="x-ac time">
<text> {{ model.time }}</text>
<i class="iconfont icon-bottom icon-down" />
</view>
</picker>
mode="time"
: 这个属性设置选择器的模式为时间选择。@change="onTimePicker"
: 这是一个事件监听器,当用户选择一个时间时触发onTimePicker
方法。:value="model.time"
: 这是一个绑定属性,表示当前选择的时间,它绑定到组件的value
prop 上。
数据模型
在 data
函数中,date
和 model.time
被定义如下:
data() {
return {
date: datetime.getCurDate(),
model: {
type: 0,
time: `${now.getHours()<10 ? '0'+now.getHours():now.getHours()}:${now.getMinutes()<10 ? '0'+now.getMinutes():now.getMinutes()}`,
// 其他属性...
},
// 其他数据...
};
}
date
: 这个属性用于存储当前选择的日期,初始值通过datetime.getCurDate()
获取当前日期。model.time
: 这个属性用于存储当前选择的时间,初始值通过格式化当前时间获取。
事件处理
在 methods
部分,定义了 onDatePicker
和 onTimePicker
方法来处理日期和时间选择事件:
methods: {
onDatePicker({ detail }) {
this.date = detail.value;
this.model.date = detail.value;
},
onTimePicker({ detail }) {
this.model.time = detail.value;
},
// 其他方法...
}
onDatePicker({ detail })
: 这个方法在用户选择一个日期时被调用。它接收一个事件对象,其中detail.value
包含用户选择的日期值。方法内部,它更新this.date
和this.model.date
为用户选择的日期。onTimePicker({ detail })
: 这个方法在用户选择一个时间时被调用。它同样接收一个事件对象,其中detail.value
包含用户选择的时间值。方法内部,它更新this.model.time
为用户选择的时间。
总结
这部分代码展示了如何在Vue组件中实现日期和时间的选择功能,包括组件的定义、数据模型的设置、以及事件处理逻辑。通过这种方式,用户可以轻松选择日期和时间,并且选择的结果会实时反映在UI上,同时更新应用的状态。这种模式是处理日期和时间选择的标准做法,可以很容易地扩展或修改以适应不同的需求。