这篇文章开头有点难以开始,这边讲一下我业务遇到的需求,我们有一个点赞、关注功能。如果不由前端来处理简单的数据一致性,那就需要在页面 onShow 的时候来加载数据。onShow 按照微信文档的说明是 “页面显示/切入前台时触发”,即我们新打开页面或者返回页面都会调用,打开页面这个不需要讲,那返回的如果想知道数据变更了则需要重新请求后端,而且还有分页来增加请求量,在另外一个是息屏,屏幕关闭重新打开也会调用 onShow 。所以我们需要修改后可以直接本地修改有关页面的数据,不过我们业务不是很复杂,只需要处理上一页的列表数据导致一致即可。
还是首先,我们弄一个评论列表页,然后点击评论可以跳转到该详情页。
components\comment-item.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <template> <view class="container-comment"> <view class="content" @click="handleToDetails">{{ item.content }}</view> <view class="like" @click="handleToggleLike">{{ has_like ? '喜欢' : '不喜欢' }}</view> </view> </template>
<script> export default { props: { item: { type: Object, default () { return {}; }, }, }, data () { return { has_like: this.item.has_like, } }, methods: { handleToggleLike () { this.has_like = !this.has_like; }, handleToDetails () { if(this.handleHasDetailsPage()) return;
return uni.navigateTo({ url: '/pages/index/details?id=' + this.item.id, }); }, handleHasDetailsPage () { const page = this.$last_page();
return page.route === 'pages/index/details'; }, }, } </script>
<style lang="scss" scoped> .container-comment { display: flex; justify-content: space-between; font-size: 24px; } </style>
|
pages\index\index.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <template> <view class="container"> <view v-if="list.length" class="list"> <comment-item v-for="item in list" :key="item.id" :item="item"></comment-item> </view> </view> </template>
<script> export default { data() { return { list: [], } }, onLoad () { this.handleInit(); }, methods: { handleInit () { return uni.request({ url: 'https://cdn.hongfs.cn/blog/uniapp-wechat-mini-program-parent-page-data-synchronization/data.json', success: (response) => { this.list = response.data.list; }, }); }, }, } </script>
|
pages\index\details.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <template> <view v-if="data.id > 0" class="container"> <comment-item :item="data"></comment-item> </view> </template>
<script> export default { data () { return { id: -1, data: {}, } }, onLoad (options) { this.id = parseInt(options.id); this.handleInit(); }, methods: { handleInit () { return uni.request({ url: 'https://cdn.hongfs.cn/blog/uniapp-wechat-mini-program-parent-page-data-synchronization/data.json', success: (response) => { const data = response.data.list;
const index = data.findIndex(item => item.id === this.id);
if(index === -1) return;
this.data = data[index]; }, }); }, }, } </script>
|
main.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import Vue from 'vue' import App from './App'
import comment_item from './components/comment_item.vue';
Vue.config.productionTip = false
Vue.prototype.$last_page = function(num = 1) { var pages = getCurrentPages(); return pages[pages.length - num]; }
Vue.component('comment-item', comment_item);
App.mpType = 'app'
const app = new Vue({ ...App }) app.$mount()
|
效果,可以看到返回后没有重新读取数据是不会有任何改变的。
同步是依靠页面栈中的 $vm 来修改页面的数据。
components\comment-item.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| <template> <view class="container-comment"> <view class="content" @click="handleToDetails">{{ item.content }}</view> <view class="like" @click="handleToggleLike">{{ has_like ? '喜欢' : '不喜欢' }}</view> </view> </template>
<script> export default { props: { item: { type: Object, default () { return {}; }, }, }, data () { return { has_like: this.item.has_like, } }, watch: { 'item.has_like' (value) { this.has_like = !!value; }, }, methods: { handleToggleLike () { this.has_like = !this.has_like;
if(!this.handleHasDetailsPage()) return;
this.$comment_like_change(this.item.id, this.has_like); }, handleToDetails () { if(this.handleHasDetailsPage()) return;
return uni.navigateTo({ url: '/pages/index/details?id=' + this.item.id, }); }, handleHasDetailsPage () { const page = this.$last_page();
return page.route === 'pages/index/details'; }, }, } </script>
<style lang="scss" scoped> .container-comment { display: flex; justify-content: space-between; font-size: 24px; } </style>
|
mian.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import Vue from 'vue' import App from './App'
import comment_item from './components/comment-item.vue';
Vue.config.productionTip = false
Vue.prototype.$last_page = function(num = 1) { var pages = getCurrentPages(); return pages[pages.length - num]; }
Vue.prototype.$comment_like_change = function(id, value) { const page = Vue.prototype.$last_page(2);
if (['pages/index/index'].indexOf(page.route) === -1) return;
const list_key = 'list';
if (!page.$vm.hasOwnProperty(list_key)) return;
page.$vm[list_key] = page.$vm[list_key].map(item => { if (item.id === id) { item.has_like = value; }
return item; }); }
Vue.component('comment-item', comment_item);
App.mpType = 'app'
const app = new Vue({ ...App }) app.$mount()
|
最终效果。