频道数据持久化:
已登录状态:
数据存储在线上后台服务器,更换不同的设备可以同步数据。把数据请求接口放到线上,根据接口文档携带参数。
未登录状态:数据存储在本地,不支持同步功能。
正确获取首页频道数据:
判断是否已登录,已登录请求获取用户频道数据。未登录,查看是否有本地存储频道列表,有直接使用,没有请求获取推荐频道数据。
获取登录用户的频道列表和获取默认推荐的频道列表是同一个数据接口。后端会根据接口中的 token 来判定返回数据。
判断是否已登录,引入vuex的State中封装的user变量,查看里面是否携带token值,有token是登录状态,无token是未登录状态
// 实现频道的切换和删除
onMyChannelClick(channel, index) {
// 判断是否是编辑状态
if (this.isEdit) {
// 是编辑状态,实现在我的频道里删除,推荐频道里添加
//判断是否是推荐频道,推荐频道不能删除 0
if (this.fiexdChannels.includes(channel.id)) {
return;
}
// 判断当前删除的频道是否在激活频道的前面,如果是,需要将激活的索引号 - 1
if (index < this.active) {
// this.active = this.active - 1 不允许在子组件内直接对父组件传过来的数据直接修改
this.$emit("updateActive", this.active - 1, true);
}
// 删除索引号对应的频道
this.myChannels.splice(index, 1);
// 实现频道删除的持久化
this.deletChannels(channel);
} else {
//非编辑状态,实现频道的切换
this.$emit("updateActive", index, false);
}
},
文章搜索功能:
创建组件并配置路由
页面布局:使用vant组件---cell,search,
创建嵌套页面:search-history.vue,search-suggestion.vue,search-result.vue
在父组件中导入,注册,使用
import SearchResult from './components/search-result'
import SearchHistory from './components/search-history'
import SearchSuggestion from './components/search-suggestion'
components: {
SearchResult,
SearchHistory,
SearchSuggestion
}
<!-- 搜索结果 -->
<search-result />
<!-- /搜索结果 --><!-- 联想建议 -->
<search-suggestion />
<!-- /联想建议 --><!-- 搜索历史记录 -->
<search-history />
<!-- /搜索历史记录 -->
条件显示:
data () {
...
isResultShow: false
}
<!-- 搜索结果 -->
<search-result v-if="isResultShow" />
<!-- /搜索结果 --><!-- 联想建议 -->
<search-suggestion v-else-if="searchText" />
<!-- /联想建议 --><!-- 搜索历史记录 -->
<search-history v-else />
<!-- /搜索历史记录 -->
实现搜索联想建议功能:
基本思路:
- 当搜索框输入内容的时候,请求加载联想建议的数据
- 将请求得到的结果绑定到模板中
基本功能:
一、将父组件中搜索框输入的内容传给联想建议子组件
二、在子组件中监视搜索框输入内容的变化,如果变化则请求获取联想建议数据
三、将获取到的联想建议数据展示到列表中
1、获取并监视内容变化:
父组件`search/index.vue`里面通过自定义属性`search-text`注入输入框内容
<!-- 搜索结果 -->
<search-result v-if="isResultShow" :search-text="searchText" />
<!-- /搜索结果 -->
子组件`search-suggestion.vue`里面定义`props`接收数据
props: {
// 接收输入框数据
searchText: {
type: String,
required: true
}
}
使用`watch`去监听`searchText`的数据变化
watch:{
searchText:{
// 当 searchText 发生改变的时候就会调用 handler 函数
// 注意:handler 函数名称是固定的
handler(value){
console.log(value)
},
immediate:true // 该回调将会在侦听开始之后被立即调用
}
}
2、请求获取展示数
定义请求方法`api/search.js`,导入使用,定义存储数据变量,定义获取数据方法,监听调用获取数据,渲染展示
import { getSearchSuggestions } from '@/api/search'
data () {
return {
suggestions: [], // 联想建议数据列表
}
}
methods: {
// 定义获取数据方法
async loadSearchSuggestions (q) {
try {
const { data } = await getSearchSuggestions(q)
this.suggestions = data.data.options
} catch (err) {
this.$toast('数据获取失败,请稍后重试')
}
}
}
watch:{
searchText:{
// 当 searchText 发生改变的时候就会调用 handler 函数
// 注意:handler 函数名称是固定的
handler(value){
this.loadSearchSuggestions(value)
},
immediate:true // 该回调将会在侦听开始之后被立即调用
}
}
<van-cell
icon="search"
v-for="(text, index) in suggestions"
:key="index"
:title="text"
>
</van-cell>
防抖优化:使用lodash插件
安装:yarn add lodash 或 npm i lodash
防抖处理:
// lodash 支持按需加载,有利于打包结果优化
import { debounce } from "lodash"
watch: {
searchText: {
// debounce 函数
// 参数1:一个函数
// 参数2:延迟时间,单位是毫秒
// 返回值:防抖之后的函数
// debounce(函数,时长) 返回一个防抖函数
handler: debounce(function (value) {
this.loadSearchSuggestions(value)
}, 200),
immediate: true // 该回调将会在侦听开始之后被立即调用
}
},
搜索关键字高亮:
例子:::::
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>')