Vue移动端项目——搜索联想建议功能的实现(结合watch属性和使用lodash防抖节流)
搜索联想建议1. 基本思路:当搜索框输入内容的时候,请求加载联想建议的数据将请求得到的结果绑定到模板中2. 基本功能一、将父组件中搜索框输入的内容传给联想建议子组件二、在子组件中监视搜索框输入内容的变化,如果变化则请求获取联想建议数据三、将获取到的联想建议数据展示到列表中父组件完整代码:<template><div class="search-container"><
·
搜索联想建议
1. 基本思路:
当搜索框输入内容的时候,请求加载联想建议的数据
将请求得到的结果绑定到模板中
2. 基本功能
一、将父组件中搜索框输入的内容传给联想建议子组件
二、在子组件中监视搜索框输入内容的变化,如果变化则请求获取联想建议数据
三、将获取到的联想建议数据展示到列表中
父组件完整代码:
<template>
<div class="search-container">
<!--搜索栏-->
<form action="/">
<van-search v-model="searchText" @search="onSearch"
@focus="isResultShow = false" @cancel="onCancel" show-action placeholder="请输入搜索关键词" />
</form>
<!--搜索结果-->
<search-results v-if="isResultShow" />
<!--联想建议-->
<search-suggestion v-else-if="searchText" :search-text="searchText"/>
<!--历史记录-->
<search-history v-else />
</div>
</template>
<script>
import SearchSuggestion from './components/search-suggestion.vue'
import SearchHistory from './components/search-history.vue'
import SearchResults from './components/search-results.vue'
export default {
name: 'SearchIndex',
data () {
return {
searchText: '', // 输入搜索框的内容
isResultShow: false // 控制搜索结果的显示状态
}
},
components: {
SearchSuggestion,
SearchHistory,
SearchResults
},
methods: {
onSearch (val) {
// 展示搜索结果
this.isResultShow = true
},
onCancel () {
this.$router.back()
}
}
}
</script>
<style scoped>
</style>
子组件完整代码:
<template>
<div class="search-suggestion">
<van-cell v-for="(str, index) in suggestions"
:key="index" icon="search" :title="str"></van-cell>
</div>
</template>
<script>
import { getSearchSuggestions } from '../../../api/search.js'
import { debounce } from 'lodash'
// /*// 函数防抖
// const fn = _.debounce(function () {
// console.log('hello')
// }, 1000)
//
// fn()
// fn()
// setTimeout(() => {
// fn()
// }, 1200)
// fn()*/
export default {
name: 'SearchSuggestion',
data () {
return {
suggestions: [] // 联想建议数据列表
}
},
props: {
searchText: {
type: String,
required: true
}
},
watch: {
// 属性名:要监视的数据的名称
// searchText () {
// console.log('je')
// }
// 监视的完整写法
searchText: {
// 当数据发生变化则会执行 handler处理函数
handler: debounce(async function () {
// 发请求
const { data } = await getSearchSuggestions(this.searchText)
this.suggestions = data.data.options
}, 200),
// async handler () {
// // 发请求
// const { data } = await getSearchSuggestions(this.searchText)
// this.suggestions = data.data.options
// },
immediate: true // 该回调将会在侦听开始之后被立即调用
}
}
}
</script>
<style scoped>
</style>
3. 防抖优化
loadsh官网
https://www.lodashjs.com/docs/lodash.debounce
1、安装 lodash
# yarn add lodash
npm i lodash
2、防抖处理
// lodash 支持按需加载,有利于打包结果优化
import { debounce } from "lodash"
不建议下面这样使用,因为这样会加载整个模块。
import _ from 'lodash'
_.debounce()
// debounce 函数
// 参数1:函数
// 参数2:防抖时间
// 返回值:防抖之后的函数,和参数1功能是一样的
onSearchInput: debounce(async function () {
const searchContent = this.searchContent
if (!searchContent) {
return
}
// 1. 请求获取数据
const { data } = await getSuggestions(searchContent)
// 2. 将数据添加到组件实例中
this.suggestions = data.data.options
// 3. 模板绑定
}, 200),
联想建议优化——高亮搜索关键字
如何将字符串中的指定字符在网页中高亮展示?
"Hello World";
将需要高亮的字符包裹 HTML 标签,为其单独设置颜色。
"Hello <span style="color: red">World</span>"
在 Vue 中如何渲染带有 HTML 标签的字符串?
data () {
return {
htmlStr: 'Hello <span style="color: red">World</span>'
}
}
<div>{{ htmlStr }}</div>
<div v-html="htmlStr"></div>
如何把字符串中指定字符统一替换为高亮(包裹了 HTML)的字符?
const str = "Hello World"
// 结果:<span style="color: red">Hello</span> World
"Hello World".replace('Hello', '<span style="color: red">Hello</span>')
// 需要注意的是,replace 方法的字符串匹配只能替换第1个满足的字符
// <span style="color: red">Hello</span> World Hello abc
"Hello World Hello abc".replace('Hello', '<span style="color: red">Hello</span>')
// 如果想要全文替换,使用正则表达式
// g 全局
// i 忽略大小写
// <span style="color: red">Hello</span> World <span style="color: red">Hello</span> abc
"Hello World Hello abc".replace(/Hello/gi, '<span style="color: red">Hello</span>')
一个小扩展:使用字符串的 split 结合数组的 join 方法实现高亮
var str = "hello world 你好 hello";
// ["", " world 你好 ", ""]
const arr = str.split("hello");
// "<span>hello</span> world 你好 <span>hello</span>"
arr.join("<span>hello</span>");
下面是具体的处理。
1、在 methods 中添加一个方法处理高亮
// 参数 source: 原始字符串
// 参数 keyword: 需要高亮的关键词
// 返回值:替换之后的高亮字符串
highlight (source, keyword) {
// /searchContent/ 正则表达式中的一切内容都会当做字符串使用
// 这里可以 new RegExp 方式根据字符串创建一个正则表达式
// RegExp 是原生 JavaScript 的内置构造函数
// 参数1:字符串,注意,这里不要加 //
// 参数2:匹配模式,g 全局,i 忽略大小写
const reg = new RegExp(keyword, 'gi')
return source.replace(reg, `<span style="color: #3296fa">${keyword}</span>`)
},
2、然后在联想建议列表项中绑定调用
<!-- 联想建议 -->
<van-cell-group v-else-if="searchContent">
<van-cell
icon="search"
v-for="(item, index) in suggestions"
:key="index"
@click="onSearch(item)"
>
<div slot="title" v-html="highlight(item, searchContent)"></div>
</van-cell>
</van-cell-group>
<!-- /联想建议 -->
完整代码:
<template>
<div class="search-suggestion">
<van-cell v-for="(str, index) in suggestions"
:key="index" icon="search" >
<div slot="title" v-html="hightlight(str)"></div>
</van-cell>
</div>
</template>
<script>
import { getSearchSuggestions } from '../../../api/search.js'
import { debounce } from 'lodash'
// /*// 函数防抖
// const fn = _.debounce(function () {
// console.log('hello')
// }, 1000)
//
// fn()
// fn()
// setTimeout(() => {
// fn()
// }, 1200)
// fn()*/
export default {
name: 'SearchSuggestion',
data () {
return {
suggestions: [] // 联想建议数据列表
}
},
props: {
searchText: {
type: String,
required: true
}
},
watch: {
// 属性名:要监视的数据的名称
// searchText () {
// console.log('je')
// }
// 监视的完整写法
searchText: {
// 当数据发生变化则会执行 handler处理函数
handler: debounce(async function () {
// 发请求
const { data } = await getSearchSuggestions(this.searchText)
this.suggestions = data.data.options
}, 200),
// async handler () {
// // 发请求
// const { data } = await getSearchSuggestions(this.searchText)
// this.suggestions = data.data.options
// },
immediate: true // 该回调将会在侦听开始之后被立即调用
}
},
methods: {
hightlight (str) {
// RegExp()是正则表达式的构造函数
// 参数1: 字符串
// 参数2: 匹配模式
// 返回值: 正则对象
const regStr = new RegExp(this.searchText, 'gi')
return str.replace(regStr, `<span style="color: red">${this.searchText}</span>`)
}
}
}
</script>
<style scoped>
</style>
更多推荐
已为社区贡献9条内容
所有评论(0)