vue3项目实战---知乎日报----详情页

目录

组件缓存

网络请求

详情页

$nextTick&& scoped


组件缓存

当首页跳转详情页应该做缓存

vue2

  <keep-alive include="Home">
    <router-view></router-view>
  </keep-alive>

vue3

<!--  Component 为渲染的组件 is控制是否-->
  <router-view v-slot="{ Component }">
    <keep-alive include="Home">
      <component :is="Component" />
    </keep-alive>
  </router-view>

网络请求

import axios from './http'
//获取新闻详情
export const NewsInfo = id => {
    return axios.get('/api/news_info', {
        params: {
            id
        }
    })
}

//获取新闻评论信息
export const StoryExtra = id => {
    return axios.get('/api/story_extra', {
        params: {
            id
        }
    })

}

详情页

  • 样式有data标识不需要/deep/             没有为组件库样式需要加
  • v-text 不识别标签,v-html可以识别标签
  • route 路由实例对象控制路由跳转  router.back()返回一级
  • route路由信息对象,获取路径参数 route.params.id获取路径参数
  • 销毁前  移除link标签避免样式冲突
  • 页面更新完毕后可以获取到dom 追加图片(类似于-$nextTick)

js创建元素&&添加标签

  • document.createElement('link')
  •  document.head.append(link)创建dom元素
  •  document.head.removeChild(link) 移除dom元素
  •   let img = document.querySelector('.img-place-holder')
  •  img.innerHTML += `<img src="${state.NewsInfo.image}" alt="">` 添加元素

link 标签

  • HTML外部资源链接元素 (<link>) 规定了当前文档与外部资源的关系。该元素最常用于链接样式表,此外也可以被用来创建站点图标(比如PC端的“favicon”图标和移动设备上用以显示在主屏幕的图标) 。
  • href:此属性指定被链接资源的URL。 URL 可以是绝对的,也可以是相对的。
  • rel 必需。定义当前文档与被链接文档之间的关系。 stylesheet样式表
<template>
  <van-skeleton title :row="5" v-if="NewsInfo === null" />
  <div class="content" v-html="NewsInfo.body" v-else> </div>
  <div class="nav-box">
    <van-icon name="arrow-left" @click="handle" />
    <van-icon name="comment-o" :badge="comments" />
    <van-icon name="good-job-o" :badge="popularity" />
    <van-icon name="star-o" color="#1989fa" />
    <van-icon name="share-o" color="#ccc" />
  </div>
</template>

<script>
import { useRouter, useRoute } from 'vue-router'
import { reactive, toRefs, onBeforeMount, onBeforeUnmount, onUpdated } from 'vue'
import { NewsInfo, StoryExtra } from '../api/index'
export default {
  name: "Detail",
  setup() {
    let state = reactive({
      comments: 0,//评论总数
      popularity: 0,//点赞数
      NewsInfo: null
    })

    //路由实例对象控制路由跳转
    const router = useRouter()
    //路由信息对象,获取路径参数
    const route = useRoute()
    //点击跳转返回上一级
    const handle = (() => {
      router.back()
    })
    //获取数据
    onBeforeMount(async () => {
      let id = route.params.id
      let result = await NewsInfo(id)
      state.NewsInfo = result
      let { comments, popularity } = await StoryExtra(id)
      state.comments = comments
      state.popularity = popularity

      //动态创建css
      let link = document.createElement('link')
      link.id = 'link'
      link.rel = 'stylesheet'
      link.href = state.NewsInfo.css[0]
      document.head.append(link)
    })

    //数据更新后,可以获取到dom 追加图片
    onUpdated(() => {
      let img = document.querySelector('.img-place-holder')
      if (img && img.innerHTML.trim() == '') {
        img.innerHTML += `<img src="${state.NewsInfo.image}" alt="">`
      }
    })

    //移除link标签避免样式冲突
    onBeforeUnmount(() => {
      let link = document.getElementById('link')
      if (!link) return
      document.head.removeChild(link)
    })
    return {
      ...toRefs(state),
      handle
    }
  },
};
</script>

<style lang="less" scoped>
.content {
  background: #fff;
  padding-bottom: 50px;
  margin: 0;

  /deep/.img-place-holder {
    overflow: hidden;
    height: 375px;

    img {
      width: 100%;
      min-height: 100%;
      margin: 0;
    }
  }
}

.nav-box {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  box-sizing: border-box;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #f4f4f4;
  height: 50px;
  padding: 0 15px;

  .van-icon:nth-child(1) {
    position: relative;

    &::after {
      position: absolute;
      content: '';
      width: 1px;
      top: -10%;
      right: -15px;
      height: 120%;
      background: #d5d5d5;
    }
  }

  /deep/.van-badge {
    background-color: transparent;
    border: none;
    color: #000;
    right: -5px;
  }
}

.van-skeleton {
  padding: 30px 15px;
}
</style>

$nextTick&& scoped

nextTick 下一轮

  • nextTick在下一次daom节点更新结束后执行其指定的回调
  • 应用场景“当改变数据后,要基于更新后的新Dom进行某些操作”

scoped样式私有化,只在当前组件生效 会在标签中加data-v-40f4caea 属性值

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值