2.递归组件的回复评论
实现方式:内部无限循环
让递归组件无限回复评论
<div class="commentItem" title="我是评论列表的子组件">
<!-- 组件递归,判断是否有parent.parent -->
<!-- 递归:内部循环,这一条为了实现无限的评论回复 -->
<item v-if='parent.parent' :parent='parent.parent' @replyItem='sendComment'></item>
21.栏目管理
添加栏目管理的入口:index添加样式
/deep/.van-sticky{
padding-right: 50px;
&::after{
content: '+';
position: absolute;
width: 51px;
height: 44px;
background-color: #fff;
top: 0;
right: 0;
text-align: center;
line-height: 42px;
font-size: 35px;
}
}
---------------------------------
document.querySelector('.van-sticky').οnclick=e=>{
console.log(e.target.className);
if(e.target.className==='van-sticky'){
this.$router.push('/cateManager')
}
}
需要处理的业务
1.获取所有栏目,加载到“点击删除频道”结构中
2.这里注意一个细节:不要考虑“关注”和“头条”
3.栏目管理的相关数据存储在本地
4.在本地存储 未添加的频道 和 已添加的频道
5.我们所操作的数据都是来自于本地
6.首页栏目数据应该来自于本地存储,当然为了首页的业务依然顺利,意味着本地存储的数组数据不能仅仅是栏目名称,还应该包含着id等类似的数据
回顾json数据(数组字符串)的操作流程
获取json格式的字符串
将字符串转换为js数组或对象
操作数组或对象
将数组或对象重新转换为字符串
存储字符串
添加组件并配置路由
{
name:'cateManager',
path:'/cateManager',
component: () =>
import ('@/views/cateManager.vue')
}
调用api方法,获取数据实现动态渲染:之前在页面栏目中有存接口
cateManager读取本地存储的栏目数据,动态渲染
async mounted () {
// 数据渲染,如果我有之前存过的栏目数据,那么我渲染之前的数据在页面,没有则发请求渲染默认的栏目数据
// 判断是否有已删除的栏目
if(localStorage.getItem('tokens_addColumnList')){
this.addColumnList=JSON.parse(
localStorage.getItem('tokens_addColumnList')
)
}
// 判断是否有已添加的栏目
if(localStorage.getItem('tokens_delColumnList')){
this.delColumnList=JSON.parse(
localStorage.getItem('tokens_delColumnList')
)
}else{
let res= await getCategory()
this.delColumnList=res.data.data
console.log(this.delColumnList);
// if(localStorage.getItem('tokens')){
// this.delColumnList=this.delColumnList.splice(2) // 干掉关注和头条
// }else{
// this.delColumnList=this.delColumnList.splice(1) // 干掉头条
// }
}
}
实现栏目的移除
removeCate(i){
console.log(this.delColumnList[i]);
// 先添加再移除
// 将当前栏目添加到“未添加栏目数组”中
this.addColumnList.push(this.delColumnList[i])
// 从已添加的栏目数组中移除当前栏目
this.delColumnList.splice(i,1)
// 将当前数据存储到本地
localStorage.setItem('tokens_delColumnList',JSON.stringify(this.delColumnList))
localStorage.setItem('tokens_addColumnList',JSON.stringify(this.addColumnList))
},
实现栏目的添加
addCate(i){
this.delColumnList.push(this.addColumnList[i])
this.addColumnList.splice(i,1)
// 将当前数据存储到本地
localStorage.setItem('tokens_delColumnList',JSON.stringify(this.delColumnList))
localStorage.setItem('tokens_addColumnList',JSON.stringify(this.addColumnList))
}
页面结构
<template>
<div class="cateManager">
<myheader title='我的栏目'>
<span slot="left" class="iconfont iconjiantou2" @click="$router.back()"></span>
</myheader>
<div class="column">
<div class="del">
<h2>点击删除以下频道</h2>
<ul>
<li v-for="(v,i) in delColumnList" :key="i" @click="removeCate(i)">{
{v.name}}</li>
</ul>
</div>
<div class="add">
<h2>点击添加以下频道</h2>
<ul>
<li v-for="(v,i) in addColumnList" :key="i" @click="addCate(i)">{
{v.name}}</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import myheader from '@/components/myheader.vue'
import {getCategory} from '@/apis/category'
export default {
data () {
return {
delColumnList:[], //可以删除的栏目
addColumnList:[] //可以添加的栏目
}
},
components:{
myheader
},
}
<style lang="less" scoped>
h2{
margin: 10px 0 0 10px;
}
ul{
display: flex;
flex-wrap: wrap;
padding: 10px;
// justify-content: space-between;
}
li{
display: flex;
justify-content: center;
width: 50px;
padding: 10px;
margin: 10px 0;
margin-right: 20px;
border: 1px solid #000;
&:nth-child(4n){
margin-right: 0px;
}
}
</style>
22.搜索
实现搜索数据的本地存储
添加组件和配置路由
{
name:'Search',
path:'/search',
component:Search
}
制作组件的结构
<template>
<div class="search">
<div class="header">
<span class="iconfont iconjiantou2" @click="$router.back()"></span>
<van-search
v-model="userKey"
placeholder="请输入搜索关键词"
shape="round"
>
</van-search>
<div @click="onSearch">搜索</div>
</div>
<div class="historyList">
<h2>历史记录</h2>
<router-link to="">美女</router-link>
<router-link to="">美女</router-link>
</div>
<div class="historyList">
<h2>搜索结果</h2>
<router-link to="">美女</router-link>
<router-link to="">美女</router-link>
</div>
</div>
</template>
<script>
export default {
data(){
return {
userKey:''
}
},
methods:{
onSearch(){
}
}
}
</script>
<style lang='less' scoped>
.header{
display: flex;
height: 50px;
justify-content: space-between;
align-items: center;
padding: 0 10px;
border-bottom: 1px solid #ccc;
.van-search{
flex: 1;
padding: 5px 12px;
}
}
.historyList{
padding:10px;
border-bottom: 1px solid #ccc;
h2{
line-height: 40px;
font-weight: bold;
}
> a {
display: block;
text-decoration: underline;
line-height: 30px;
color:#666;
}
}
</style>
添加api方法
// 7.搜索文章
export const searchArticle = (params)=>{
return axios({
url:`/post_search`,
params
})
}
---------------------------------------
<div class="historyList">
<h2>搜索结果</h2>
<router-link :to="{path:`/articleDetail/${item.id}`}" v-for='item in searchList' :key='item.id'>{
{
item.title}}</router-link>
</div>
调用方法实现搜索
async onSearch(key){
this.searchList.length = 0
let res = await searchArticle({
keyword:key})
if(res.data.data.length > 0){
this.searchList = res.data.data
}
// 将当前的搜索关键字存储到本地
let arr = this.getdata()
// 判断当前关键字是否已经存在
let index = arr.indexOf(key)
if(index !== -1){
arr.splice(index,1)
}
// unshift:在数组的最前面插入数据
arr.unshift(key)
localStorage.setItem('toutiao_search_history_52',JSON.stringify(arr))
},
// 获取之前存储的历史关键字
getdata(){
return JSON.parse(localStorage.getItem('toutiao_search_history_52')|| '[]')
}
页面打开时,加载历史记录
mounted(){
this.historyList = this.getdata()
}
---------------------------------------
<div class="historyList">
<h2>历史记录</h2>
<a href='javascript:;' v-for='(item,index) in historyList' :key='index' @click="onSearch(item)">{
{
item}}</a>
</div>