-
zhangwei
2025-03-05 16213c0f85aa3ac8317797bf4a05fd12940e16d3
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<template>
    <view
        class="u-radio-group"
        :class="bemClass"
            :style="radioGroupStyle"
    >
        <slot></slot>
    </view>
</template>
 
<script>
    import { props } from './props';
    import { mpMixin } from '../../libs/mixin/mpMixin';
    import { mixin } from '../../libs/mixin/mixin';
    import { addUnit, addStyle, deepMerge } from '../../libs/function/index';
 
    /**
     * radioRroup 单选框父组件
     * @description 单选框用于有一个选择,用户只能选择其中一个的场景。搭配u-radio使用
     * @tutorial https://ijry.github.io/uview-plus/components/radio.html
     * @property {String | Number | Boolean}    value             绑定的值
     * @property {Boolean}                        disabled        是否禁用所有radio(默认 false )
     * @property {String}                        shape            外观形状,shape-方形,circle-圆形(默认 circle )
     * @property {String}                        activeColor        选中时的颜色,应用到所有子Radio组件(默认 '#2979ff' )
     * @property {String}                        inactiveColor    未选中的颜色 (默认 '#c8c9cc' )
     * @property {String}                        name            标识符
     * @property {String | Number}                size            组件整体的大小,单位px(默认 18 )
     * @property {String}                        placement        布局方式,row-横向,column-纵向 (默认 'row' )
     * @property {String}                        label            文本
     * @property {String}                        labelColor        label的颜色 (默认 '#303133' )
     * @property {String | Number}                labelSize        label的字体大小,px单位 (默认 14 )
     * @property {Boolean}                        labelDisabled    是否禁止点击文本操作checkbox(默认 false )
     * @property {String}                        iconColor        图标颜色 (默认 '#ffffff' )
     * @property {String | Number}                iconSize        图标的大小,单位px (默认 12 )
     * @property {Boolean}                        borderBottom    placement为row时,是否显示下边框 (默认 false )
     * @property {String}                        iconPlacement    图标与文字的对齐方式 (默认 'left' )
     * @property {Object}                        gap                item 之间的间距
   * @property {Object}                        customStyle        组件的样式,对象形式
     * @event {Function} change 任一个radio状态发生变化时触发
     * @example <u-radio-group v-model="value"></u-radio-group>
     */
    export default {
        name: 'u-radio-group',
        mixins: [mpMixin, mixin, props],
        computed: {
            // 这里computed的变量,都是子组件u-radio需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
            // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-radio-group)
            // 拉取父组件新的变化后的参数
            parentData() {
                // #ifdef VUE3
                return [this.modelValue, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape,
                    this.iconSize, this.borderBottom, this.placement
                ]
                // #endif
                // #ifdef VUE2
                return [this.value, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape,
                    this.iconSize, this.borderBottom, this.placement
                ]
                // #endif
                
            },
            bemClass() {
                // this.bem为一个computed变量,在mixin中
                return this.bem('radio-group', ['placement'])
            },
            radioGroupStyle() {
                const style = {
                    gap: addUnit(this.gap)
                };
                return deepMerge(style, addStyle(this.customStyle));
            }
        },
        watch: {
            // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
            parentData() {
                if (this.children.length) {
                    this.children.map(child => {
                        // 判断子组件(u-radio)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
                        typeof(child.init) === 'function' && child.init()
                    })
                }
            },
        },
        data() {
            return {
            }
        },
        created() {
            this.children = []
        },
        // #ifdef VUE3
        emits: ['update:modelValue', 'change'],
        // #endif
        methods: {
            // 将其他的radio设置为未选中的状态
            unCheckedOther(childInstance) {
                this.children.map(child => {
                    // 所有子radio中,被操作组件实例的checked的值无需修改
                    if (childInstance !== child) {
                        child.checked = false
                    }
                })
                const {
                    name
                } = childInstance
                // 通过emit事件,设置父组件通过v-model双向绑定的值
                // #ifdef VUE3
                this.$emit("update:modelValue", name);
                // #endif
                // #ifdef VUE2
                this.$emit("input", name);
                // #endif
                // 发出事件
                this.$emit('change', name)
            },
        }
    }
</script>
 
<style lang="scss" scoped>
    @import "../../libs/css/components.scss";
 
    .u-radio-group {
        flex: 1;
 
        &--row {
            /* #ifndef APP-NVUE */
            display: flex;
            /* #endif */
            flex-flow: row wrap;
        }
 
        &--column {
            @include flex(column);
        }
    }
</style>