美文网首页
vue自定义listView

vue自定义listView

作者: HCL黄 | 来源:发表于2019-10-23 18:49 被阅读0次
    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>
    
    这里需要注意的是
    • 导入import tableView from "@/components/listView.vue",并且在components定义为tableView也可以自己命名自己喜欢的,然后这样才能在<template>里使用<tableView></tableView>
    • 属性lists的数据可以根据自己需要进行修改,注释都有说明
    • didClickBtn方法检测内容是否填写采用的是比较笨的方式,后续有时间了再来优化
    • didClickItem方法就是前面我们在子组件里定义的,有个title参数传过来,然后我们就可以使用this.$refs.child.setDetailValue对子组件进行赋值操作
    下面布局就不多说了,都是简单的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>
    

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

    相关文章

      网友评论

          本文标题:vue自定义listView

          本文链接:https://www.haomeiwen.com/subject/upekvctx.html