vue自定义listView

2019-10-23  本文已影响0人  HCL黄
222.gif

第一步打开HBuilderX,新建项目命名为textApp

A2796E2A-3CC9-43D5-B2F3-43878867F091.png

第二步新建目录命名为components

1848999C-304D-42F3-A895-DDC51053CE38.png

第三步新建vue文件命名为listView

D77F012E-08B9-4A1C-8AED-F515381BE8B2.png

第四步在listView.vue文件编辑代码

<template>
    <view>
        <view class="content">
            <view class="centerV">
                <view v-for="(item, index) in lists" :key='index' class="centerV-item" :class="index!=0?'centerV-itemT':''">
                    <view v-for="(subItem, subIndex) in lists[index]" :key='subIndex' class="centerV-subItem" @click="didClickItem(subItem)">
                        <!-- 上边内容 -->
                        <view class="subItem-topV">
                            <view class="subItem-left">
                                <image class="subLeft-img" :src="subItem.icon"></image>
                                <text class="subLeft-title">{{subItem.title}}</text>
                                <!-- 0:#AAAAAA 12px 1:#FFAC1C 14px -->
                                <text class="subLeft-subTitle" :class="subItem.subTitleType==1?'subLeft-subTitle1' :''">{{subItem.subTitle}}</text>
                            </view>

                            <view class="subItem-right">
                                <!-- rightType = 0:普通样式 1:输入框样式 -->
                                <view v-if="subItem.rightType==0" class="subRight-normalV">
                                    <text v-if="subItem.detail.length==0" class="subRight-title">{{subItem.detailPlaceholder}}</text>
                                    <text v-else class="subRight-title1">{{subItem.detail}}</text>
                                    <!-- 0:蓝色下箭头 1:灰色右箭头 2:问好图标 -->
                                    <image class="subRight-img" :class="subItem.rightIconType==0?'blueDown-img' :subItem.rightIconType==1?'grayArrow-img' :subItem.rightIconType==2?'blueMark-img' :''"
                                     :src="subItem.rightIcon"></image>
                                </view>
                                <!-- rightType = 0:普通样式 1:输入框样式 -->
                                <view v-else-if="subItem.rightType==1" class="subRight-inputV">
                                    <!-- <textarea @input="textareaInput" class="cnt-textarea textareaFont" placeholder="请输入内容" placeholder-style="color:#999999"/> -->
                                    <input :id="subItem.title" @input="inputChange" class="inputV-input" :type="subItem.inputType" :placeholder="subItem.inputPlaceholder"
                                     placeholder-style="color:#999999" />
                                    <text class="inputV-text">{{subItem.inputUnit}}</text>
                                </view>
                            </view>
                        </view>

                        <!-- 下边分割线 -->
                        <view v-if="subIndex!=lists[index].length-1" class="subItem-btmV"></view>
                    </view>
                </view>
            </view>

        </view>

    </view>
</template>

<script>
    export default {
        props: {
            pLists: {
                typs: Array, // 类型数组
                default: [], // 默认值
                required: true, // 是否必传
            }
        },
        mounted() {
            this.lists = this.pLists; // 内部接收
        },
        data() {
            return {
                lists: [] // 定义属性
            }
        },
        methods: {
            // 为detail赋值
            setDetailValue: function(string, value) {
                var datas = this.lists;
                for (let i = 0; i < datas.length; i++) {
                    var item = datas[i];
                    for (let j = 0; j < item.length; j++) {
                        var subItem = item[j];
                        var title = subItem.title;
                        if (title == string) {
                            subItem.detail = value;
                        }
                    }
                }
            },
            // 为subTitle赋值
            setSubTitleValue: function(string, value) {
                var datas = this.lists;
                for (let i = 0; i < datas.length; i++) {
                    var item = datas[i];
                    for (let j = 0; j < item.length; j++) {
                        var subItem = item[j];
                        var title = subItem.title;
                        if (title == string) {
                            subItem.subTitle = value;
                        }
                    }
                }
            },

            // 点击每一行
            didClickItem: function(subItem) {
                var title = subItem.title;
                this.$emit('didClickItem', title);
            },
            // 监听输入框改变
            inputChange: function(event) {
                console.log(event.detail.value);
                console.log(event.currentTarget.id);
                var value = event.detail.value;
                var ID = event.currentTarget.id;
                var datas = this.lists;
                for (let i = 0; i < datas.length; i++) {
                    var item = datas[i];
                    for (let j = 0; j < item.length; j++) {
                        var subItem = item[j];
                        var title = subItem.title;
                        if(title == ID) {
                            subItem.detail = value;
                        }
                    }
                }
            }
        },
    }
</script>
1、这里注意export default里的props对外属性定义,主要是让外面传对应的数据进来
2、didClickItem方法里的this.$emit是子组件来触发父组件的方法,这里的this是父组件
3、this.$emit('didClickItem', title);括号里是方法名和参数

第五步在index.vue文件编辑代码

<template>
    <view>
        <view class="content">
            <view class="topV">
                <image class="topV-img" src="../../static/fd_008.png"></image>
                <text class="topV-text">我是顶部广告信息</text>
            </view>

            <!-- 中间列表 -->
            <tableView class="centerV" ref="child" :pLists="lists" @didClickItem="didClickItem"></tableView>

            <view class="bottomV">
                <!-- 合作服务协议 -->
                <view class="btm-agreeV">
                    <view class="agreeV-left" @click="didClickAgree">
                        <image class="aLeft-img" :src="isAgree?'../../static/fd_012.png':'../../static/fd_011.png'"></image>
                        <text class="aLeft-text">阅读并同意</text>
                    </view>
                    <view class="agreeV-right" @click="didClickService">《合作服务协议》</view>
                </view>
                <!-- 发布按钮 -->
                <view class="btm-releaseV" @click="didClickBtn">
                    <text class="releaseV-text">发布</text>
                </view>
            </view>
        </view>

        <view style="height: 94upx;"></view>
        <view class="phoneV" @click="didClickPhone">
            <text class="phoneV-normalText">如有其他疑问请咨询客服:</text>
            <text class="phoneV-highlightedText">{{phone}}</text>
        </view>

    </view>
</template>
这里注意ref="child"是将child指向tableView这个组件,后面就可以使用this.$refs.child来调用组件里面的方法了
<script>
    import tableView from "@/components/listView.vue"
    export default {
        data() {
            return {
                isAgree: false, // 是否勾选合作服务协议
                phone: '123456', // 客服电话
                lists: [
                    [{
                            icon: '../../static/fd_001.png',
                            title: '第一组第一行',
                            subTitle: '',
                            subTitleType: 0, // 0:#AAAAAA 12px 1:#FFAC1C 14px
                            detailPlaceholder: '右边占位说明',
                            detail: '',
                            rightIcon: '../../static/fd_013.png',
                            rightIconType: 0, // 0:蓝色下箭头 1:灰色右箭头 2:问好图标
                            rightType: 0, // 0:普通样式 1:输入框样式
                            inputType: '', // 当rightType==1时,该值有效。text文本,number数字,idcard身份证 digit带小数点的数字键盘
                            inputPlaceholder: '', // 当rightType==1时,该值有效。
                            inputUnit: '', // 当rightType==1时,该值有效。
                        },
                        {
                            icon: '../../static/fd_002.png',
                            title: '第一组第二行',
                            subTitle: '',
                            subTitleType: 0, // 0:#AAAAAA 12px 1:#FFAC1C 14px
                            detailPlaceholder: '右边占位说明',
                            detail: '',
                            rightIcon: '../../static/fd_010.png',
                            rightIconType: 1, // 0:蓝色下箭头 1:灰色右箭头 2:问好图标
                            rightType: 0, // 0:普通样式 1:输入框样式
                            inputType: '', // 当rightType==1时,该值有效。text文本,number数字,idcard身份证 digit带小数点的数字键盘
                            inputPlaceholder: '', // 当rightType==1时,该值有效。
                            inputUnit: '', // 当rightType==1时,该值有效。
                        }
                    ],
                    [{
                            icon: '../../static/fd_003.png',
                            title: '第二组第一行',
                            subTitle: '',
                            subTitleType: 0, // 0:#AAAAAA 12px 1:#FFAC1C 14px
                            detailPlaceholder: '右边占位说明',
                            detail: '',
                            rightIcon: '../../static/fd_010.png',
                            rightIconType: 1, // 0:蓝色下箭头 1:灰色右箭头 2:问好图标
                            rightType: 0, // 0:普通样式 1:输入框样式
                            inputType: '', // 当rightType==1时,该值有效。text文本,number数字,idcard身份证 digit带小数点的数字键盘
                            inputPlaceholder: '', // 当rightType==1时,该值有效。
                            inputUnit: '', // 当rightType==1时,该值有效。
                        },
                        {
                            icon: '../../static/fd_004.png',
                            title: '第二组第二行',
                            subTitle: '(非必填)',
                            subTitleType: 0, // 0:#AAAAAA 12px 1:#FFAC1C 14px
                            detailPlaceholder: '右边占位说明',
                            detail: '',
                            rightIcon: '../../static/fd_010.png',
                            rightIconType: 1, // 0:蓝色下箭头 1:灰色右箭头 2:问好图标
                            rightType: 0, // 0:普通样式 1:输入框样式
                            inputType: '', // 当rightType==1时,该值有效。text文本,number数字,idcard身份证 digit带小数点的数字键盘
                            inputPlaceholder: '', // 当rightType==1时,该值有效。
                            inputUnit: '', // 当rightType==1时,该值有效。
                        },
                        {
                            icon: '../../static/fd_005.png',
                            title: '第二组第三行',
                            subTitle: '(另外描述)',
                            subTitleType: 0, // 0:#AAAAAA 12px 1:#FFAC1C 14px
                            detailPlaceholder: '右边占位说明',
                            detail: '',
                            rightIcon: '../../static/fd_013.png',
                            rightIconType: 0, // 0:蓝色下箭头 1:灰色右箭头 2:问好图标
                            rightType: 0, // 0:普通样式 1:输入框样式
                            inputType: '', // 当rightType==1时,该值有效。text文本,number数字,idcard身份证 digit带小数点的数字键盘
                            inputPlaceholder: '', // 当rightType==1时,该值有效。
                            inputUnit: '', // 当rightType==1时,该值有效。
                        }
                    ],
                    [{
                        icon: '../../static/fd_006.png',
                        title: '第三组第一行',
                        subTitle: '200元',
                        subTitleType: 1, // 0:#AAAAAA 12px 1:#FFAC1C 14px
                        detailPlaceholder: '右边占位说明',
                        detail: '',
                        rightIcon: '../../static/fd_009.png',
                        rightIconType: 2, // 0:蓝色下箭头 1:灰色右箭头 2:问好图标
                        rightType: 0, // 0:普通样式 1:输入框样式
                        inputType: '', // 当rightType==1时,该值有效。text文本,number数字,idcard身份证 digit带小数点的数字键盘
                        inputPlaceholder: '', // 当rightType==1时,该值有效。
                        inputUnit: '', // 当rightType==1时,该值有效。
                    }],
                    [
                        {
                            icon: '../../static/fd_006.png',
                            title: '第四组第一行',
                            subTitle: '',
                            subTitleType: 0,// 0:#AAAAAA 12px 1:#FFAC1C 14px
                            detailPlaceholder: '',
                            detail: '',
                            rightIcon: '',
                            rightIconType: 0, // 0:蓝色下箭头 1:灰色右箭头 2:问好图标
                            rightType: 1, // 0:普通样式 1:输入框样式
                            inputType: 'number', // 当rightType==1时,该值有效。text文本,number数字,idcard身份证 digit带小数点的数字键盘
                            inputPlaceholder: '输入框占位说明', // 当rightType==1时,该值有效。
                            inputUnit: '(元)', // 当rightType==1时,该值有效。
                        }
                    ]
                ]
            }
        },
        onLoad() {

        },
        methods: {
            // 点击勾选按钮
            didClickAgree: function() {
                this.isAgree = !this.isAgree;
            },
            // 点击合作服务协议
            didClickService: function() {
                console.log('点击合作服务协议');
            },
            // 点击发布按钮
            didClickBtn: function() {
                var message = '';
                var datas = this.lists;
                for (let i = 0; i < datas.length; i++) {
                    var item = datas[i];
                    if (message || message.length != 0) break;
                    for (let j = 0; j < item.length; j++) {
                        var subItem = item[j];
                        if (!subItem.detail || subItem.detail.length == 0) {
                            var title = subItem.title;
                            if (title == '第一组第一行') {
                                message = '请选择第一组第一行的内容'
                            } else if (title == '第一组第二行') {
                                message = '请选择第一组第二行的内容'
                            } else if (title == '第二组第一行') {
                                message = '请选择第二组第一行的内容'
                            } else if (title == '第二组第三行') {
                                message = '请选择第二组第三行的内容'
                            } else if(title == '第四组第一行') {
                                message = '请在第四组第一行输入内容'
                            }
                            // 跳出循环
                            break;
                        }
                    }
                }

                if (message.length != 0) {
                    uni.showToast({
                        title: message,
                        icon: 'none',
                        duration: 2000
                    })
                    return;
                }
                if (!this.isAgree) {
                    uni.showToast({
                        title: '请阅读并同意《合作服务协议》',
                        icon: 'none',
                        duration: 2000
                    })
                    return;
                }

                console.log('可以发布了');
            },
            // 点击客服电话
            didClickPhone: function() {
                console.log('点击客服电话');
            },
            // 点击每一行
            didClickItem: function(title) {
                if (title == '第一组第一行') {
                    console.log('点击第一组第一行');
                    // 获取到的是组件实例,可以使用组件的所有方法
                    this.$refs.child.setDetailValue('第一组第一行', '第一组第一行内容')
                } else if (title == '第一组第二行') {
                    this.$refs.child.setDetailValue('第一组第二行', '第一组第二行内容')
                } else if (title == '第二组第一行') {
                    this.$refs.child.setDetailValue('第二组第一行', '第二组第一行内容')
                } else if (title == '第二组第二行') {
                    this.$refs.child.setDetailValue('第二组第二行', '第二组第二行内容')
                } else if (title == '第二组第三行') {
                    this.$refs.child.setDetailValue('第二组第三行', '第二组第三行内容')
                } else if (title == '第三组第一行') {
                    this.$refs.child.setDetailValue('第三组第一行', '第三组第一行内容')
                    
                }
            },
        },

        components: {
            tableView
        }
    }
</script>
这里需要注意的是
下面布局就不多说了,都是简单的flex布局
<style>
    page {
        background-color: rgb(241, 241, 241);
    }

    .content {}

    /* 最顶部内容 */
    .topV {
        background-color: #FFFFFF;
        height: 80upx;
        width: 100%;
        display: flex;
        flex-direction: row;
        align-items: center;
    }

    .topV-img {
        margin-left: 30upx;
        margin-right: 10upx;
        width: 32upx;
        height: 32upx;
    }

    .topV-text {
        color: #FF9500;
        font-family: PingFang-SC-Medium;
        font-size: 28upx;
    }

    /* 中间内容 */
    .centerV {
        margin-top: 30upx;
    }

    /* 底部内容 */
    .bottomV {
        display: flex;
        flex-direction: column;
        margin-top: 30upx;
    }

    /* 服务协议 */
    .btm-agreeV {
        display: flex;
        flex-direction: row;
        height: 34upx;
    }

    .agreeV-left {
        display: flex;
        flex-direction: row;
        align-items: center;
    }

    .aLeft-img {
        width: 28upx;
        height: 28upx;
        margin-right: 20upx;
        margin-left: 30upx;
    }

    .aLeft-text {
        font-family: PingFang-SC-Medium;
        font-size: 24upx;
        color: #787878;
    }

    .agreeV-right {
        font-family: PingFang-SC-Medium;
        font-size: 26upx;
        color: #3ABBFF;
    }

    /* 发布按钮 */
    .btm-releaseV {
        margin-top: 60upx;
        margin-left: 30upx;
        margin-right: 30upx;
        background-color: #3ABBFF;
        height: 88upx;
        border-radius: 10upx;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .releaseV-text {
        font-family: PingFang-SC-Medium;
        color: #FFFFFF;
        font-size: 34upx;
    }

    /* 客服电话 */
    .phoneV {
        display: flex;
        justify-content: center;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        line-height: 94upx;
        background-color: rgb(241, 241, 241);
        z-index: 999;
    }

    .phoneV-normalText {
        font-family: PingFang-SC-Medium;
        color: #999999;
        font-size: 28upx;
    }

    .phoneV-highlightedText {
        font-family: PingFang-SC-Medium;
        color: #3ABBFF;
        font-size: 28upx;
    }
</style>

最后就可以在浏览器打开观看效果了

上一篇下一篇

猜你喜欢

热点阅读