自定义组件
如果你看到这里,那不得不恭喜你,你已经理解了 Taro 中最复杂的概念:入口组件和页面组件,并了解了它们是如何(通过配置文件)交互的。接下来的内容,如果你已经熟悉了 React 或 Vue 以及 Web 开发的话,那就太简单了:
我们先把首页写好,首页的逻辑很简单:把论坛最新的帖子展示出来。
- React
- Vue
src/pages/index/index.vue
<template>
<view class="index">
<thread-list :threads="threads" :loading="loading" />
</view>
</template>
<script>
import Vue from 'vue'
import Taro from '@tarojs/taro'
import api from '../../utils/api'
import ThreadList from '../../components/thread_list.vue'
export default {
components: {
'thread-list': ThreadList,
},
data() {
return {
loading: true,
threads: [],
}
},
async created() {
try {
const res = await Taro.request({
url: api.getLatestTopic(),
})
this.loading = false
this.threads = res.data
} catch (error) {
Taro.showToast({
title: '载入远程数据错误',
})
}
},
}
</script>
了解更多
可能你会注意到在一个 Taro 应用中发送请求是 Taro.request()
完成的。 和页面配置、全局配置一样,Taro 的 API 规范也是基于微信小程序而制定的,并对全平台进行统一。 你可以通过在 API 文档 找到所有 API。
在我们的首页组件里,还引用了一个 ThreadList
组件,我们现在来实现它:
- React
- Vue
src/components/thread_list.vue
<template>
<view className="thread-list">
<loading v-if="loading" />
<thread
v-else
v-for="t in threads"
:key="t.id"
:node="t.node"
:title="t.title"
:last_modified="t.last_modified"
:replies="t.replies"
:tid="t.id"
:member="t.member"
/>
</view>
</template>
<script>
import Vue from 'vue'
import Loading from './loading.vue'
import Thread from './thread.vue'
export default {
components: {
loading: Loading,
thread: Thread,
},
props: {
threads: {
type: Array,
default: [],
},
loading: {
type: Boolean,
default: true,
},
},
}
</script>
src/components/thread.vue
<template>
<view class="thread" @tap="handleNavigate">
<view class="info">
<view>
<image :src="member.avatar_large | url" class="avatar" />
</view>
<view class="middle">
<view :class="usernameCls"> {{member.username}} </view>
<view class="replies">
<text class="mr10">{{time}}</text>
<text>评论 {{replies}}</text>
</view>
</view>
<view class="node">
<text class="tag">{{node.title}}</text>
</view>
</view>
<text class="title">{{title}}</text>
</view>
</template>
<script>
import Vue from 'vue'
import { eventCenter } from '@tarojs/taro'
import Taro from '@tarojs/taro'
import { timeagoInst, Thread_DETAIL_NAVIGATE } from '../utils'
import './thread.css'
export default {
props: ['title', 'member', 'last_modified', 'replies', 'node', 'not_navi', 'tid'],
computed: {
time() {
return timeagoInst.format(this.last_modified * 1000, 'zh')
},
usernameCls() {
return `author ${this.not_navi ? 'bold' : ''}`
},
},
filters: {
url(val) {
return 'https:' + val
},
},
methods: {
handleNavigate() {
const { tid, not_navi } = this.$props
if (not_navi) {
return
}
eventCenter.trigger(Thread_DETAIL_NAVIGATE, this.$props)
// 跳转到帖子详情
Taro.navigateTo({
url: '/pages/thread_detail/thread_detail',
})
},
},
}
</script>
这里可以发现我们把论坛帖子渲染逻辑拆成了两个组件,并放在 src/components
文件中,因为这些组件是会在其它页面中多次用到。 拆分组件的力度是完全由开发者决定的,Taro 并没有规定组件一定要放在 components
文件夹,也没有规定页面一定要放在 pages
文件夹。
另外一个值得注意的点是:我们并没有使用 div
/span
这样的 HTML 组件,而是使用了 View
/Text
这样的跨平台组件。