龙空技术网

Vue3 搜索联想组件 Makeit Search

麦可易特网 527

前言:

当前姐妹们对“css3搜索框代码”大约比较注意,朋友们都需要学习一些“css3搜索框代码”的相关知识。那么小编同时在网上网罗了一些有关“css3搜索框代码””的相关文章,希望我们能喜欢,朋友们一起来了解一下吧!

最近基于 Vue3.0.5 + Vite 开发了一个搜索联想组件,该组件的应用非常广泛,谷歌、百度、天猫、京东等,很多站点上随处可见搜索联想的功能。根据给定的关键词,搜索出相关的内容并给予提示。该组件大致实现的功能如下:

1. 支持搜索结果列表的动态配置

2. 搜索框能满足大部分的定制需求

3. 支持远程搜索

4. 支持分页配置

5. 支持延迟搜索 / 定制点击事件等

6. 更多 ...

先上几张效果图看看:

效果示例 - 1

效果示例 - 2

效果示例 - 3

效果示例 - 4

效果示例 - 5

没有太多的难点,图个方便,封装成组件给有需要的人直接拿来用,唯一要注意的是用户自定义结果列表模板的实现,下面就讲讲这个点。

定义模板

假设用户定义的模板如下所示

// MiSearchKey 为搜索组件内定义的另外一个组件// 其中 name 指待替换的字段名称(其它略过...)<mi-search :data="data" search-key="title">    <template v-slot:itemTemplate>        <div class="avatar">            <mi-search-key type="image" tag="img" name="avatar"></mi-search-key>        </div>        <div class="content">            <mi-search-key name="content"></mi-search-key>        </div>    </template></mi-search>
获取模板
// 获取模板const template = getSlotContent(this, 'itemTemplate')// 具体实现const getSlotContent = (    instance: any,    prop = 'default',    options = instance,    exec = true) => {    let content = undefined    if (instance.$) {        const temp = instance[prop]        if (temp !== undefined) {            return typeof temp === 'function' && exec ? temp(options) : temp        } else {            content = instance.$slots[prop]            content = content && exec ? content(options) : content        }    } else if (isVNode(instance)) {        const temp = instance.props && instance.props[prop]        if (temp !== undefined && instance.props !== null) {            return typeof temp === 'function' && exec ? temp(options) : temp        } else if (instance.type === Fragment) {            content = instance.children        } else if (instance.children && instance.children[prop]) {            content = instance.children[prop]            content = content && exec ? content(options) : content        }    }    if (Array.isArray(content)) {        content = flattenChildren(content)        content = content.length === 1 ? content[0] : content        content = content.length === 0 ? undefined : content    }    return content}// 封装 Childrenconst flattenChildren = (children = []) => {    children = Array.isArray(children) ? children : [children]    const res = []    children.forEach((child) => {        if (Array.isArray(child)) {            res.push(...flattenChildren(child))        } else if (child && child.type === Fragment) {            res.push(...flattenChildren(child.children))        } else if (child && isVNode(child) && !tools.isEmptyElement(child)) {            res.push(child)        } else if (tools.isValid(child)) {            res.push(child)        }    })    return res}

获取模板的实现代码

解析模板

// 渲染结果列表renderCustomResultListElem(templates: VNode[], item: any) {    const elems = []    for (let i = 0, l = templates.length; i < l; i++) {        const curTemplate = templates[i]        if (isVNode(curTemplate)) {            let elem = cloneVNode(curTemplate)            if ((curTemplate.type as any).name === MiSearchKey.name) {                const tag = curTemplate.props.tag                const name = curTemplate.props.name                const type = curTemplate.props.type                elem = createVNode(                    <MiSearchKey name={name}                        data={tools.htmlEncode(item[name])}                        tag={tag}                        type={type}>                    </MiSearchKey>                )            }            elem = this.getCustomItemElem(elem, item)            elems.push(elem)        }    }    return elems}// 渲染每一项的内容 Item// 遇到 MiSearchKey 组件,则进行替换操作getCustomItemElem(node: VNode, item: any) {    if (        node &&        node.children &&        node.children.length > 0    ) {        const data = {...item}        const children = []        for (let i = 0, l = node.children.length; i < l; i++) {            if (isVNode(node.children[i])) {                let child = cloneVNode(node.children[i])                if ((child.type as any).name === MiSearchKey.name) {                    const tag = child.props.tag                    const name = child.props.name                    const type = child.props.type                    children[i] = createVNode(                        <MiSearchKey name={name}                            data={tools.htmlEncode(item[name])}                            tag={tag}                            type={type}>                        </MiSearchKey>                    )                } else children[i] = child                child = this.getCustomItemDetailElem(child, data)            }        }        node.children = children    }    return node}
遍历结果

最后就很简单,直接遍历搜索结果,每条结果调用上述解析模板的方法,进行内容的替换,再渲染即可。

for (let n = 0, len = this.list.length; n < len; n++) {    const item = {...this.list[n]}    // ...}
PS

基本上没有什么难点,唯一要注意的点在 今天,Vue3 联想搜索组件开发遇见了个小问题 中也简单地描述了一下,但并没有展开讲,今天是展开这个点详细讲述了一下代码实现。

组件我已经发布到 npm,有需要的可以搜索 makeit-search 试试,至于示例地址,我放置在文章末尾的扩展链接中了,需要源码的同学可以前往 Github 下载,地址为

今天就先这样了 ~

标签: #css3搜索框代码