项目分析五

     一、首页-频道编辑——数据持久化

// 1.封装添加请求的方法,在src/api/channel.js中
export const addUserChannel = channels => {
  return request({
    method: 'PATCH',
    url: '/v1_0/user/channels',
    data: {
      channels: [channels]
    }
  })
}

// 2.在src/views/home/components/channel-edit.vue中导入请求方法
import {addUserChannel} from "@/api/channel";
import {mapState} from 'vuex'
import {setItem} from '@/utils/storage'

computed: {
...mapState(['user']),
....
}

// 3.修改添加频道的处理逻辑
    async onAddChannels(channels) {
      // console.log(22);
      this.myChannel.push(channels);
      // 添加数据持久化处理
      if (this.user) {
        try {
          // 已登录,就把数据请求接口放到线上
          await addUserChannel({
            id: channels.id, // 频道id
            seq: this.myChannel.length,  // 序号
          });
        } catch (err) {
          this.$toast("请求失败,请稍后再试");
        }
      } else {
        // 未登录,把数据存储到本地
        setItem("TOUTIAO_CHANNELS", this.myChannel);
      }
    },

  

// 4.封装删除请求的方法在src/api/channel.js中
export const deleteUserChannel = (channelID) => {
  return request({
    method: 'DELETE',
    url: `/v1_0/user/channels/${channelID}`,
  })
}

// 5.在src/views/home/components/channel-edit.vue中导入请求方法
import {.... deleteUserChannel} from"@/api/channels";

// 6. 修改删除频道的处理逻辑
    onMyChannels(channels, index) {
      if (this.idEdit) {
        ....
        this.myChannel.splice(index, 1); // 处理删除持久化
        this.deleteChannel(channels);
        ....
    },
    async deleteChannel(channels) {
      try {
        if (this.user) {
        // 已登录,就将数扰更新到线上
          await deleteUserChannel(channels.id);
        } else {
        // 未登录,就将数据更新到本地
          setItem("TOUTIAO_CHANNELS", this.myChannel);
        }
      } catch (err) {
        this.$toast("获取失败");
      }
    },
// 7.在src/views/home/index.vue中导入
import { mapState } from "vuex";
import { getItem } from "@/utils/storage";

// 8.正确获取首页频道数据
methods:{
...,
   async loadUserChannels() {
      try {
        // const { data } = await getUserChannels();
        // console.log(data);
        // this.UserChannels = data.data.channels;
        let channels = []; // 定义一个空数组
        if (this.user) {
        // 已登录,请求获取用户频道列表
          const { data } = await getUserChannels();
          // console.log(data);
          channels = data.data.channels;
        } else {
        // 未登录,判断是否有本地的频道列表数据
          const localChannels = getItem("TOUTIAO_CHANNELS");
          // 有的话,就拿来使用
          if (localChannels) {
            channels = localChannels;
          } else {
          // 没有的话,请求获取默认频道列表
            const { data } = await getUserChannels();
            channels = data.data.channels;
          }
        }
        this.UserChannels = channels // 让之前就定义的频道列表UserChannels来接收channels
      } catch (err) {
        this.$toast("获取频道列表失败");
      }
    },
    ...
 }

二、首页-文章搜索——创建组件并配置路由

// 1.在src/views下创建search文件夹
// 2.在src/views/search创建文件index.vue,并搭建基本样式






// 3.在src/router/index.js中添加一级路由
// 路由映射数组
const routes = [
      {....},
      {....},
  	  {
    	path: "/search",
    	name: "search",
    	component: () => import("@/views/search"),
  	  },
];

// 4.在src/views/home/index.vue中添加跳转
     
        搜索
      

三、文章搜索——完成搜索栏布局



四、文章搜索——创建组件

// 1.在src/views/search中创建文件夹components,在此文件夹下创建三个文件:search-history.vue  search-suggestion.vue  search-result.vue  并搭建基本样式
// 2. search-history.vue 搭建基本样式






// 3.search-suggestion.vue  搭建基本样式






// 4.search-result.vue  搭建基本样式




// 5、在search/index.vue 中导入
import SearchResult from './components/search-result'
import SearchSuggestion from './components/search-suggestion'
import SearchHistory from './components/search-history'

// 6.注册
components: {
   SearchResult,
   SearchSuggestion,
   SearchHistory
},
data() {
   return {
     searchText: "", // 绑定输入框变量
     isResultShow:false, // 8.在data 中添加数据用来控制搜索结果的显示状态
   };
 },

// 7.使用

  // 9.添加判断显示条件 



  // 9.添加判断显示条件



  // 9.添加判断显示条件

五、文章搜索——实现搜索联想功能

// 1.在父组件src/views/search/index.vue中自定义属性

    


// 2.在子组件src/views/search/components/search-suggestion.vue中接收数据
props: {
    // 接收输入框数据
    searchText: {
      type: String,
      required: true
    }
},
// 3.侦听数据变化
  watch: {
    searchText:{
      handler(value){
        console.log(value);
        // 8.监听调用获取数据
        this.loadSearchSuggestions(value)
      },
      immediate:true
    }
  },

// 4.封装请求,在src/api下创建search.js文件
import request from '@/utils/request'

export const getSearchSuggestions = (q) => {
  return request({
    method: 'GET',
    url: '/v1_0/suggestion',
    params:{
        q
    }
  })
}

// 5.在子组件src/views/search/components/search-suggestion.vue中使用
import { getSearchSuggestions } from '@/api/search'
// 6.定义变量用来储存数数据
data () {
    return {
      suggestions: [], // 联想建议数据列表
    }
  },
 // 7. 定义获取数据方法
 methods: {
    async loadSearchSuggestions (q) {
      try {
        const { data } = await getSearchSuggestions(q)
        this.suggestions = data.data.options
      } catch (err) {
        this.$toast('数据获取失败,请稍后重试')
      }
    }
 }
 
 // 9.渲染
 

六、文章搜索——搜索结果

// 1.在src/views/search/components/search-suggestion.vue中给van-cell增加点击事件,触发自定义事件
    


// 2.父组件src/views/search/index.vue中的监听自定义事件
    
 // 可以直接给监听事件onSearch

    
  methods: {
     onSearch (val) {
    //  console.log(val);
    // 更新文本框内容
    this.searchText = val
    // 打开搜索结果
    this.isResultShow = true
},    

// 3.在父组件src/views/search/index.vue中将输入框的数据传递给搜索结果组件search-result.vue
 
 
 
 // 4.在子组件src/views/search/components/search-result.vue中接收数据
 props: {
	// 接收传递进入的数据
    searchText: {
      type: String,
      required: true
    }
}

// 5.在src/api/search.js中封装请求
export const getSearchResult = (params) => {
    return request({
      method: 'GET',
      url: '/v1_0/search',
      params
    })
  }

// 6.在子组件src/views/search/components/search-result.vue中导入方法,
import { getSearchResult } from '@/api/search'
// 7.在子组件src/views/search/components/search-result.vue中请求获取数据
    data () {
    return {
      list: [],  // 定义存储变量
      loading: false,
      finished: false,
      page: 1,
      perPage: 20,
      error: false
    }
  },
    methods: {
    async onLoad () {
      try {
        // 1. 请求获取数据
        const { data } = await getSearchResult({
          page: this.page, // 页码
          per_page: this.perPage, // 每页大小
          q: this.searchText // 查询关键词
        })
        // 2. 将数据添加到数组列表中
        const { results } = data.data
        this.list.push(...results)
        // 3. 将本次加载中的 loading 关闭
        this.loading = false
        // 4. 判断是否还有数据
        if (results.length) {
          // 如果有,则更新获取下一个数据的页码
          this.page++
        } else {
          // 如果没有,则将加载状态 finished 设置为结束
          this.finished = true
        }
      } catch (err) {
        // 展示加载失败的提示状态
        this.error = true
        // 加载失败了 loading 也要关闭
        this.loading = false
      }
    }
  },
// 7.在子组件src/views/search/components/search-result.vue中渲染

七、文章搜索——实现搜索关键字高亮

// 在 methods 中添加一个方法处理高亮
highlight (text) {
    const highlightStr = `${this.searchText}`

    // 正则表达式 // 中间的内容都会当作匹配字符来使用,而不是数据变量
    // 如果需要根据数据变量动态的创建正则表达式,则手动 new RegExp
    // RegExp 正则表达式构造函数
    //    参数1:匹配模式字符串,它会根据这个字符串创建正则对象
    //    参数2:匹配模式,要写到字符串中
    const reg = new RegExp(this.searchText, 'gi')
    return text.replace(reg, highlightStr)
}

    
    
// 调用方法

八、文章搜索——实现防抖

// 1.安装  查看中文文档地址https://www.lodashjs.com/
yarn add lodash
// 2.导入 在src/views/search/components/search-result.vue中使用局部导入
import { debounce } from "lodash"
// 3.使用
watch: {
    searchText: {
      // debounce 函数
      // 参数1:一个函数
      // 参数2:延迟时间,单位是毫秒
      // 返回值:防抖之后的函数
      //   debounce(函数,时长)  返回一个防抖函数
      handler: debounce(function (value) {
        this.loadSearchSuggestions(value)
      }, 2000),
      immediate: true
    }
  },

你可能感兴趣的:(vue.js)