产生原因:
一直以来, 使用 uniapp 封装组件, 然后通过使用 props 来给组件传参控制组件内容, 或者使用 slot , 但是比如页面有多个弹窗, 则需要修改数据然后再 更新显示隐藏, 如果是在某个流程里面, 比如 常见的 Confirm 类, 则需要设置组件的回调来接受事件, 其实是比较麻烦的, 今天经过一系列的分析, 终于想到了一个方案,
主要用到的 api 就是微信的 selectComponent()
大概思路就是,. 我正常弹窗, 然后在 弹窗 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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<style scoped> .page { margin: 50px; } </style> <template> <div class="page" v-if="openPopup"> <h1>{{content}}:{{test}}</h1> <button @click="okay">确定</button> <button @click="cancel">取消</button> </div> </template> <script> /** * Created by iyahe@qq.com * Date: 2021/7/13 * Time: 3:53 下午 * Description: */ export default { name: "popup", mixins: [], props: {}, data() { return { content: '我是组件', openPopup: false, onConfirm:function (){}, onCancel: function (){}, test: '' } }, computed: {}, watch: {}, components: {}, methods: { close () { // this.$set(this,'test', Math.random()) this.$mp.component.setData({ openPopup: false }) }, okay (e) { // 不知道什么原因, 这里直接给 onConfirm 赋值, 第一次会无法更新数据,所以才用原生方法用 setData 赋值 const { onConfirm } = this.$mp.component.data this.close() onConfirm(e); }, cancel(e){ // 同上 const { onCancel } = this.$mp.component.data this.close() onCancel(e); } }, created() {}, mounted() {} } </script> |
然后是我们的弹窗处理类, 里面用来处理弹窗的赋值
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 |
/** * Created by 天明 * Date: 2021/7/13 * Time: 4:06 下午 * Description: */ export default { alert(message) { const page = getCurrentPages(); // 如果有多个弹窗, 这个 #popup 可以当做参数传入进来, const popup = page[0].selectComponent('#popup') return new Promise((resolve, reject) => { popup.setData({ 'content': message, 'onConfirm': (e) => { resolve(e) }, 'onCancel': (e) => { reject(e) }, 'openPopup': true }); }) } }; |
最后使我们使用的页面里面
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 |
<style scoped> .page { margin: 50px; } </style> <template> <div class="page" v-if="openPopup"> <h1>{{content}}:{{test}}</h1> <button @click="okay">确定</button> <button @click="cancel">取消</button> </div> </template> <script> /** * Created by iyahe@qq.com * Date: 2021/7/13 * Time: 3:53 下午 * Description: */ export default { name: "popup", mixins: [], props: {}, data() { return { content: '我是组件', openPopup: false, onConfirm:function (){}, onCancel: function (){}, test: '' } }, computed: {}, watch: {}, components: {}, methods: { close () { this.$set(this,'test', Math.random()) this.$mp.component.setData({ openPopup: false }) }, okay (e) { // 不知道什么原因, 这里直接给 onConfirm 赋值, 第一次会无法更新数据,所以才用原生方法用 setData 赋值 const { onConfirm } = this.$mp.component.data this.close() onConfirm(e); }, cancel(e){ // 同上 const { onCancel } = this.$mp.component.data this.close() onCancel(e); } }, created() {}, mounted() {} } </script> |
经过简单的扩展后, 就可以愉快的使用了,
再也不用 比如用户点了确认, 然后 this.$emit(‘okay’,xxx), 父组件 接收 okay 的回调,再去处理业务逻辑了,
现在直接可以
1 2 3 4 5 |
message.alert('你好呀, 我是传入的内容').then(_=>{ // 点了确认后的业务逻辑 }).catch(_=>{ // 点了取消后的业务逻辑 }) |