{"id":16634921,"url":"https://github.com/ruochuan12/vant-weapp-analysis","last_synced_at":"2026-05-07T10:32:12.252Z","repository":{"id":50659319,"uuid":"448542668","full_name":"ruochuan12/vant-weapp-analysis","owner":"ruochuan12","description":"经常用 vant-weapp 开发小程序，却不知道如何开发一个组件？学！","archived":false,"fork":false,"pushed_at":"2023-04-05T15:07:48.000Z","size":14525,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-08T16:07:39.075Z","etag":null,"topics":["miniprogram","ui","vant","vant-weapp","vue"],"latest_commit_sha":null,"homepage":"https://juejin.cn/post/7126545101228081188","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruochuan12.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-01-16T12:07:05.000Z","updated_at":"2023-03-07T11:03:40.000Z","dependencies_parsed_at":"2022-09-18T19:01:15.493Z","dependency_job_id":null,"html_url":"https://github.com/ruochuan12/vant-weapp-analysis","commit_stats":null,"previous_names":["ruochuan12/vant-weapp-analysis"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ruochuan12/vant-weapp-analysis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruochuan12%2Fvant-weapp-analysis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruochuan12%2Fvant-weapp-analysis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruochuan12%2Fvant-weapp-analysis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruochuan12%2Fvant-weapp-analysis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruochuan12","download_url":"https://codeload.github.com/ruochuan12/vant-weapp-analysis/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruochuan12%2Fvant-weapp-analysis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32733459,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["miniprogram","ui","vant","vant-weapp","vue"],"created_at":"2024-10-12T05:49:28.489Z","updated_at":"2026-05-07T10:32:12.236Z","avatar_url":"https://github.com/ruochuan12.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\nhighlight: darcula\ntheme: smartblue\n---\n\n# 经常用 vant-weapp 开发小程序，却不知道如何开发一个组件？\n\n## 1. 前言\n\n\u003e大家好，我是[若川](https://lxchuan12.gitee.io)。**为了能帮助到更多对源码感兴趣、想学会看源码、提升自己前端技术能力的同学**。我倾力持续组织了一年[每周大家一起学习200行左右的源码共读活动](https://juejin.cn/post/7079706017579139102)，感兴趣的可以 [点此扫码加我微信 `ruochuan02` 参与](https://juejin.cn/pin/7217386885793595453)。\n\n想学源码，极力推荐关注我写的专栏（目前是掘金专栏关注人数第一，3.6K+人）[《学习源码整体架构系列》](https://juejin.cn/column/6960551178908205093) 包含`jQuery`、`underscore`、`lodash`、`vuex`、`sentry`、`axios`、`redux`、`koa`、`vue-devtools`、`vuex4`、`koa-compose`、`vue 3.2 发布`、`vue-this`、`create-vue`、`玩具vite`等20余篇源码文章。\n\n## 2. stepper 步进器\n\n\u003e感兴趣的小伙伴，可以克隆我的仓库调试学习 [git clone https://github.com/lxchuan12/vant-weapp-analysis.git](https://github.com/lxchuan12/vant-weapp-analysis.git)。\n\n我们开发微信小程序时经常会使用到 `stepper` 步进器组件。本文就来分析 `vant-weapp` `stepper` 步进器源码实现。\n\n相比于原生 `JS` 等源码。我们或许更应该学习，正在使用的组件库的源码，因为有助于帮助我们写业务和写自己的组件。\n\n[stepper 步进器文档](https://vant-contrib.gitee.io/vant-weapp/#/stepper)\n\nstepper 图\n\n![stepper 图](./images/stepper.png)\n\n如何开发一个微信小程序组件，可以参考官方文档。\n[微信小程序自定义组件 文档](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/)\n\n看完本文，你将学到：\n\n```bash\n1. 学会如何通过调试看源码\n2. 如何写一个微信小程序的组件\n3. 学会开发一个 stepper 步进器组件\n```\n\n## 3. 克隆项目 \u0026\u0026 调试\n\n```bash\ngit clone https://github.com/vant-ui/vant-weapp.git\n\n# 也可以克隆我的仓库\ngit clone https://github.com/lxchuan12/vant-weapp-analysis.git\ncd vant-weapp-analysis/vant-weapp\n\nyarn install\nyarn run dev\n```\n\n由于 `yarn run dev` 没有压缩代码，本文就基于运行 `dev` 后没有压缩的代码进行讲述。\n\n打开[微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html)，把 `vant-weapp/example` 目录添加进去就可以预览示例了。注意：如果没有自己的 `appid`，可以选择测试号。\n\n添加编译模式，启动页面为 `pages/stepper/index`，即可单独调试该页面。\n\n关于更多 `JS` 调试，之前文章写过，[新手向：前端程序员必学基本技能——调试JS代码](https://juejin.cn/post/7030584939020042254)，这里就不赘述。\n\n[前端容易忽略的 debugger 调试技巧](https://mp.weixin.qq.com/s/VOoDHqIo4gh3scHVNxk3lA)\n\n附上一张图。\n\n![debugger](./images/debugger.png)\n\n我们找到对应的文件，查看下组件源码的整体结构。\n\n## 4. 整体结构\n\n### 4.1 组件的 wxml 结构\n\n`wxml` 部分相对简单清晰，这里就不过多讲述。\n\n```html\n\u003c!-- vant-weapp/example/dist/stepper/index.wxml --\u003e\n\u003cwxs src=\"../wxs/utils.wxs\" module=\"utils\" /\u003e\n\u003cwxs src=\"./index.wxs\" module=\"computed\" /\u003e\n\n\u003cview class=\"{{ utils.bem('stepper', [theme]) }} custom-class\"\u003e\n  \u003cview\n    wx:if=\"{{ showMinus }}\"\n    data-type=\"minus\"\n    style=\"{{ computed.buttonStyle({ buttonSize }) }}\"\n    class=\"minus-class {{ utils.bem('stepper__minus', { disabled: disabled || disableMinus || currentValue \u003c= min }) }}\"\n    hover-class=\"van-stepper__minus--hover\"\n    hover-stay-time=\"70\"\n    bind:tap=\"onTap\"\n    bind:touchstart=\"onTouchStart\"\n    bind:touchend=\"onTouchEnd\"\n  \u003e\n    \u003cslot name=\"minus\" /\u003e\n  \u003c/view\u003e\n  \u003cinput\n    always-embed=\"{{ false }}\"\n    type=\"{{ integer ? 'number' : 'digit' }}\"\n    class=\"input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}\"\n    style=\"{{ computed.inputStyle({ buttonSize, inputWidth }) }}\"\n    value=\"{{ currentValue }}\"\n    focus=\"{{ focus }}\"\n    disabled=\"{{ disabled || disableInput }}\"\n    always-embed=\"{{ alwaysEmbed }}\"\n    bindinput=\"onInput\"\n    bind:focus=\"onFocus\"\n    bind:blur=\"onBlur\"\n  /\u003e\n  \u003cview\n    wx:if=\"{{ showPlus }}\"\n    data-type=\"plus\"\n    style=\"{{ computed.buttonStyle({ buttonSize }) }}\"\n    class=\"plus-class {{ utils.bem('stepper__plus', { disabled: disabled || disablePlus || currentValue \u003e= max }) }}\"\n    hover-class=\"van-stepper__plus--hover\"\n    hover-stay-time=\"70\"\n    bind:tap=\"onTap\"\n    bind:touchstart=\"onTouchStart\"\n    bind:touchend=\"onTouchEnd\"\n  \u003e\n    \u003cslot name=\"plus\" /\u003e\n  \u003c/view\u003e\n\u003c/view\u003e\n```\n\n### 4.2 组件的 JS 结构\n\n```js\n// vant-weapp/example/dist/stepper/index.js\nimport { VantComponent } from '../common/component';\n// 不等于 undefined 也不等于 null\n// export function isDef(value) {\n//    return value !== undefined \u0026\u0026 value !== null;\n// }\nimport { isDef } from '../common/validator';\n// 长按开始时间\nconst LONG_PRESS_START_TIME = 600;\n// 长按定时器\nconst LONG_PRESS_INTERVAL = 200;\n// add num and avoid float number\n// 为了解决类似 0.1 + 0.2 !== 0.3 的问题\n// 0.1 + 0.2 === 0.30000000000000004\nfunction add(num1, num2) {\n    const cardinal = Math.pow(10, 10);\n    return Math.round((num1 + num2) * cardinal) / cardinal;\n}\n// 判断两个字符串相等\nfunction equal(value1, value2) {\n    return String(value1) === String(value2);\n}\ndebugger;\nVantComponent({\n    field: true,\n    classes: ['input-class', 'plus-class', 'minus-class'],\n    // 代码省略 props、created、methods 函数中若干内容\n    props: {\n        value: {\n            type: null,\n            observer: 'observeValue',\n        },\n    },\n    data: {\n        currentValue: '',\n    },\n    created() {\n        this.setData({\n            currentValue: this.format(this.data.value),\n        });\n    },\n    methods: {\n    },\n});\n```\n\n### 4.3 VantComponent 组件\n\n我们可以在 `vant-weapp/example/dist/stepper/index.js` 文件的 `VantComponent({})` 上方加上 `debugger;` 调试源码。按进入函数按钮。\n\n```js\n// vant-weapp/example/dist/stepper/index.js\ndebugger;\nVantComponent({})\n```\n\n调试如图所示：\n\n![微信开发者工具调试](./images/debugger-wx.png)\n\n```js\n// vant-weapp/example/dist/common/component.js\nimport { basic } from '../mixins/basic';\nfunction mapKeys(source, target, map) {\n    Object.keys(map).forEach((key) =\u003e {\n        if (source[key]) {\n            target[map[key]] = source[key];\n        }\n    });\n}\nfunction VantComponent(vantOptions) {\n    const options = {};\n    // Vue的写法转换成小程序写法\n    mapKeys(vantOptions, options, {\n        data: 'data',\n        props: 'properties',\n        mixins: 'behaviors',\n        methods: 'methods',\n        beforeCreate: 'created',\n        created: 'attached',\n        mounted: 'ready',\n        destroyed: 'detached',\n        classes: 'externalClasses',\n    });\n    // add default externalClasses\n    // 外部样式类，也就是为什么我们可以定义 custom-class 修改样式\n    options.externalClasses = options.externalClasses || [];\n    options.externalClasses.push('custom-class');\n    // add default behaviors\n    // behaviors 是用于组件间代码共享的特性，类似于一些编程语言中的 “mixins” 或 “traits”。\n    // 每个 behavior 可以包含一组属性、数据、生命周期函数和方法。\n    // 组件引用它时，它的属性、数据和方法会被合并到组件中，生命周期函数也会在对应时机被调用。\n    options.behaviors = options.behaviors || [];\n    options.behaviors.push(basic);\n    // add relations\n    // 添加关系 类似 ul li 组件 List =\u003e ListItem 组件\n    const { relation } = vantOptions;\n    if (relation) {\n        options.relations = relation.relations;\n        options.behaviors.push(relation.mixin);\n    }\n    // 添加内置的 behavior 参考链接\n    // https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html#wx-form-field\n    // https://developers.weixin.qq.com/miniprogram/dev/component/form.html\n    // map field to form-field behavior\n    if (vantOptions.field) {\n        options.behaviors.push('wx://form-field');\n    }\n    // add default options\n    // 参考：https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html\n    options.options = {\n        // 在组件定义时的选项中启用多 slot 支持\n        multipleSlots: true,\n        addGlobalClass: true,\n    };\n    Component(options);\n}\nexport { VantComponent };\n```\n\n#### 4.3.1 Behavior 如同 mixins\n\n```js\n// vant-weapp/example/dist/mixins/basic.js\nexport const basic = Behavior({\n    methods: {\n        $emit(name, detail, options) {\n            this.triggerEvent(name, detail, options);\n        },\n        set(data) {\n            this.setData(data);\n            return new Promise((resolve) =\u003e wx.nextTick(resolve));\n        },\n    },\n});\n```\n\n看完了 `VantComponent` 函数。\n再来看看组件的初始化。\n\n## 5. 组件初始化\n\n```js\nVantComponent({\n    field: true,\n    classes: ['input-class', 'plus-class', 'minus-class'],\n    // 代码省略 props、data、created、methods 函数中内容\n    props: {\n        value: {\n            type: null,\n            observer: 'observeValue',\n        },\n        integer: {\n            type: Boolean,\n            observer: 'check',\n        },\n        decimalLength: {\n            type: Number,\n            value: null,\n            observer: 'check',\n        },\n    },\n    data: {\n        currentValue: '',\n    },\n    created() {\n        this.setData({\n            currentValue: this.format(this.data.value),\n        });\n    },\n    methods: {\n        // 观测 value，如果 value、currentValue 两者不相等，以格式化后的 value 值赋值给 currentValue\n        observeValue() {\n            const { value, currentValue } = this.data;\n            if (!equal(value, currentValue)) {\n                this.setData({ currentValue: this.format(value) });\n            }\n        },\n        // 观测格式化后的 currentValue，如果两者不相等，以 value 值赋值给 currentValue\n        check() {\n            const val = this.format(this.data.currentValue);\n            if (!equal(val, this.data.currentValue)) {\n                this.setData({ currentValue: val });\n            }\n        },\n        // filter illegal characters\n        // 格式化 value\n        filter(value) {\n            value = String(value).replace(/[^0-9.-]/g, '');\n            if (this.data.integer \u0026\u0026 value.indexOf('.') !== -1) {\n                value = value.split('.')[0];\n            }\n            return value;\n        },\n        // 限制 value 的范围\n        // limit value range\n        format(value) {\n            value = this.filter(value);\n            // 处理范围 最大值和最小值\n            // format range\n            value = value === '' ? 0 : +value;\n            value = Math.max(Math.min(this.data.max, value), this.data.min);\n            // 格式化小数位数\n            // format decimal\n            if (isDef(this.data.decimalLength)) {\n                value = value.toFixed(this.data.decimalLength);\n            }\n            return value;\n        },\n    },\n});\n```\n\n接着我们继续调试加减号基础功能。\n\n## 6. 点击加号/减号\n\n### 6.1 onTap 函数\n\n```html\n\u003cview\n    bind:tap=\"onTap\"\n\u003e\u003c/view\u003e\n```\n\n我们可以在 `onTap` 函数处断点，或者加上 `debugger`。\n\n```js\nonTap(event) {\n    debugger;\n    // data-type=\"minus\"\n    const { type } = event.currentTarget.dataset;\n    this.type = type;\n    this.onChange();\n},\n```\n\n再在 `onChange` 函数断点，点击进入函数按钮操作。\n接着我们来看 `onChange` 函数实现。\n\n### 6.2 onChange 函数\n\n```js\nonChange() {\n    const { type } = this;\n    // 超出了，派发超过 overlimit 事件\n    if (this.isDisabled(type)) {\n        this.$emit('overlimit', type);\n        return;\n    }\n    // 差值 step 步长\n    const diff = type === 'minus' ? -this.data.step : +this.data.step;\n    // 格式化\n    const value = this.format(add(+this.data.currentValue, diff));\n    this.emitChange(value);\n    this.$emit(type);\n},\n```\n\n### 6.3 isDisabled 函数\n\n最大最小值比较等。\n\n```js\nisDisabled(type) {\n    const { disabled, disablePlus, disableMinus, currentValue, max, min, } = this.data;\n    if (type === 'plus') {\n        return disabled || disablePlus || currentValue \u003e= max;\n    }\n    return disabled || disableMinus || currentValue \u003c= min;\n},\n```\n\n### 6.4 emitChange 函数\n\n```js\nemitChange(value) {\n    if (!this.data.asyncChange) {\n        this.setData({ currentValue: value });\n    }\n    this.$emit('change', value);\n},\n```\n\n如果不是异步，则直接赋值给 `currentValue`。\n并且派发 `change` 事件。\n\n断点调试在 `$emit` 函数。点击开发者工具的进入函数按钮。\n\n### 6.5 $emit 函数\n\n在上文提到过 `Behavior` `basic`。类似于 `vue` 中的 `$emit`。\n\n```js\n$emit(name, detail, options) {\n    this.triggerEvent(name, detail, options);\n},\n```\n\n[组件间通信与事件 文档](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html)\n\n```js\n\u003c!-- 当自定义组件触发“myevent”事件时，调用“onMyEvent”方法 --\u003e\n\u003ccomponent-tag-name bindmyevent=\"onMyEvent\" /\u003e\n\u003c!-- 或者可以写成 --\u003e\n\u003ccomponent-tag-name bind:myevent=\"onMyEvent\" /\u003e\n```\n\n```js\n\u003c!-- 在自定义组件中 --\u003e\n\u003cbutton bindtap=\"onTap\"\u003e点击这个按钮将触发“myevent”事件\u003c/button\u003e\n```\n\n```js\nComponent({\n  properties: {},\n  methods: {\n    onTap: function(){\n      var myEventDetail = {} // detail对象，提供给事件监听函数\n      var myEventOption = {} // 触发事件的选项\n      this.triggerEvent('myevent', myEventDetail, myEventOption)\n    }\n  }\n})\n```\n\n我们接着看输入框输入。\n\n## 7. 输入框输入 onInput 函数\n\n```html\n\u003cinput \n    bindinput=\"onInput\"\n/\u003e\n```\n\n```js\nonInput(event) {\n    debugger;\n    const { value = '' } = event.detail || {};\n    // allow input to be empty\n    if (value === '') {\n        return;\n    }\n    let formatted = this.filter(value);\n    // 限制最大的小数位\n    // limit max decimal length\n    if (isDef(this.data.decimalLength) \u0026\u0026 formatted.indexOf('.') !== -1) {\n        const pair = formatted.split('.');\n        formatted = `${pair[0]}.${pair[1].slice(0, this.data.decimalLength)}`;\n    }\n    this.emitChange(formatted);\n},\n```\n\n## 8. 输入框聚焦/失焦\n\n```html\n\u003cinput\n    bind:focus=\"onFocus\"\n    bind:blur=\"onBlur\"\n/\u003e\n```\n\n`focus`、`blur`事件\n\n```js\nonFocus(event) {\n    this.$emit('focus', event.detail);\n},\nonBlur(event) {\n    const value = this.format(event.detail.value);\n    this.emitChange(value);\n    this.$emit('blur', Object.assign(Object.assign({}, event.detail), { value }));\n},\n```\n\n## 9. 长按加号/减号 累计功能\n\n```html\n\u003cview\n    bind:touchstart=\"onTouchStart\"\n    bind:touchend=\"onTouchEnd\"\n\u003e\u003c/view\u003e\n```\n\n```js\nconst LONG_PRESS_START_TIME = 600;\nconst LONG_PRESS_INTERVAL = 200;\nlongPressStep() {\n    this.longPressTimer = setTimeout(() =\u003e {\n        this.onChange();\n        this.longPressStep();\n    }, LONG_PRESS_INTERVAL);\n},\nonTouchStart(event) {\n    debugger;\n    // 如果不支持长按，默认支持\n    if (!this.data.longPress) {\n        return;\n    }\n    // 清除定时间\n    clearTimeout(this.longPressTimer);\n    const { type } = event.currentTarget.dataset;\n    this.type = type;\n    this.isLongPress = false;\n    this.longPressTimer = setTimeout(() =\u003e {\n        this.isLongPress = true;\n        this.onChange();\n        this.longPressStep();\n    }, LONG_PRESS_START_TIME);\n},\nonTouchEnd() {\n    if (!this.data.longPress) {\n        return;\n    }\n    // 长按结束，清除定时器\n    clearTimeout(this.longPressTimer);\n},\n```\n\n## 10. 总结\n\n行文至此，就基本接近尾声了。我们从 `vant-weapp` 常用的 `stepper` 步进器组件源码出发。整体源码并不长。\n\n我们通过调试方法，分析了整体结构，`VantComponent` 函数组件的实现，还有加号减号的功能基本实现，input输入功能、聚焦失焦、还有长按累计的功能等。\n\n或许我们自己实现，可能就写的一团糟。所以，相比于原生 `JS` 等源码。我们或许更应该学习，正在使用的组件库的源码，因为有助于帮助我们写业务和写自己的组件。\n\n不过大多时候，学习源码或许是重要但不紧急的事情。除了公司项目外，我们可以多尝试学习开源项目的源码，从而贡献自己的代码，拥抱开源，会让自己更上一层楼。\n\n感兴趣的小伙伴，可以克隆我的仓库调试学习 [git clone https://github.com/lxchuan12/vant-weapp-analysis.git](https://github.com/lxchuan12/vant-weapp-analysis.git)。\n\n---\n\n**如果看完有收获，欢迎点赞、评论、分享支持。你的支持和肯定，是我写作的动力**~\n\n我倾力持续组织了一年[每周大家一起学习200行左右的源码共读活动](https://juejin.cn/post/7079706017579139102)，感兴趣的可以[点此扫码加我微信 `ruochuan02` 参与](https://juejin.cn/pin/7217386885793595453)。\n\n另外，想学源码，极力推荐关注我写的专栏[《学习源码整体架构系列》](https://juejin.cn/column/6960551178908205093)，目前是掘金关注人数（4.1k+人）第一的专栏，写有20余篇源码文章。包含`jQuery`、`underscore`、`lodash`、`vuex`、`sentry`、`axios`、`redux`、`koa`、`vue-devtools`、`vuex4`、`koa-compose`、`vue 3.2 发布`、`vue-this`、`create-vue`、`玩具vite`、`create-vite` 等20余篇源码文章。\n\n我正在参与掘金技术社区创作者签约计划招募活动，[点击链接报名投稿](https://juejin.cn/post/7112770927082864653)。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruochuan12%2Fvant-weapp-analysis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruochuan12%2Fvant-weapp-analysis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruochuan12%2Fvant-weapp-analysis/lists"}