仿知乎日报项目总结

1.vant组件库 Rem 布局适配

安装postcss-pxtorem,用于将 px 单位转化为 rem 单位,安装lib-flexible 用于设置 rem 基准值。新建postcss.config.js文件,引入以下代码。并在main.js引入amfe-flexible

module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue: 37.5,
      propList: ['*'],
    },
  },
}; 

2.全局样式处理使得font-size最大不超过75px,屏幕最大宽度不超过750px。不能在index.html中控制font-size,因为index.html在app.vue之前加载。我们可以在utils中定义一个函数获取html的font-size大小和页面宽度,控制使其在规定范围。

3.在主页头部引入最开始默认的静态图片时,不能在setup中返回图片的相对路径然后在模板中动态绑定,因为webpack打包后就没有assets文件夹了,原图片地址变成另一个图片地址。在vue中动态绑定的图片不能使用相对地址,可以通过require引入相对路径,webpack打包的时候就不会打包了。还可以通过import动态导入,导入的就是打包后的地址。

import timg from "@/assets/images/timg.jpg"

4.首页头部封装成一个单独的组件,在utils中封装一个格式化时间的组件,home组件给head组件传递时间,如果没有传递时间则获取现在的时间,在头部组件中通过计算属性获取head中展示的时间并转化为满足的格式。再在模板中进行展示。

head中将时间转化为符合条件的格式

   let timeNow = computed(() => {
    
    
      let time = props.time || null;
      let [month, day] = formatTime(time, "{1}-{2}").split("-");
      let area = [
        "一月",
        "二月",
        "三月",
        "四月",
        "五月",
        "六月",
        "七月",
        "八月",
        "九月",
        "十月",
        "十一月",
        "十二月",
      ];
      return {
    
    
        month: area[month - 1],
        day,
      };
    });

格式化时间的format函数:

export const formatTime = function formatTime(time, template) {
    // 如果传入的时间不是一个字符串,就获取现在的时间
    if (typeof time !== 'string') {
        time = new Date().toLocaleString('zh-CN', { hour12: false });
    }
    // 如果传入的模板不是一个字符串 就使用下面的默认模板
    if (typeof template !== 'string') {
        template = '{0}年{1}月{2}日 {3}:{4}:{5}';
    }
    // 解析出年月日等信息  
    let arr = [];
    // 日期可能存在的格式  '20211025' '2021/12/25' '2021-12-5 10:00:00' 
    if (/^\d{8}$/.test(time)) {
        let [, $1, $2, $3] = /^(\d{4})(\d{2})(\d{2})$/.exec(time);
        arr.push($1, $2, $3);
    } else {
        arr = time.match(/\d+/g);
    }
    // 把获取的数据替换模板
    return template.replace(/\{(\d+)\}/g, (_, $1) => {
        let item = arr[$1] || "00";
        if (item.length < 2) item = "0" + item;
        return item;
    })
}

5.轮播图部分优化:

​ ①轮播图图片懒加载

​ ②从服务器拿的数据,以后不需要再改细节,我们可以通过Object.freeze(对象)做冻结,使数据对象不会成为响应式,提升性能。

Object.freeze() 可以冻结一个对象,冻结之后不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。该方法返回被冻结的对象。

首页获取服务器数据时就用到了Object.freeze()

 // 第一次加载首页获取数据
    onBeforeMount(async () => {
      let { date, stories, top_stories } = await api.queryNewsLatest();
      // 修改数据
      state.today = date;
      state.bannerList = Object.freeze(top_stories);
      state.newsList.push(Object.freeze({ date, stories }));
    });

6.我发现当我从首页进入详情页后,如果再返回首页,页面又会回到最顶端,这显然不是最好的,不能给用户很好的体验感。所以我们应该使用keep-alive缓存home组件,使得我们从详情页返回主页的时候依然能停留在之前的位置。Vue3中keep-alive的用法与Vue2不同,具体用法如下:

 <router-view v-slot="{ Component }">
    <keep-alive include="Home">
      <component :is="Component" />
    </keep-alive>
  </router-view>

7.详情页的主体部分展示的内容及样式是服务器直接返回回来的,我们向服务器发请求获取详情页的展示信息,当数据返回回来之后,我们在主体盒子中通过v-html插入展示的数据,通过动态创建并追加link标签添加样式。为了防止离开详情页后样式影响到别的组件,需要在组件销毁前移除link标签。

8.点击登录按钮后发生的那些事。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AjKaKaZq-1678344606750)(C:\Users\雨落倾城夏末凉\AppData\Roaming\Typora\typora-user-images\image-20230210151614601.png)]

9.有部分接口向服务器发请求时需要携带token,time,sign。这个操作在封装axios请求的请求头中进行。

axios.interceptors.request.use(config => {
    // 针对于部分接口,我们携带令牌和签名信息
    let apiList = ["/check_login", "/user_info", "/user_update", "/store", store_remove", "/store_list"]
    let token = localStorage.getItem("token");
    if (apiList.includes(config.url.replace("/api", "")) && token) {
        let time = +new Date();
        let sign = md5(`${token}@${time}@zhufeng`);
        config.headers['authorzation'] = token;
        config.headers['time'] = time;
        config.headers['sign'] = sign;
    }
    return config;
});

10.登录页用到了van-form和轻提示等基本组件。登录页需要在失去焦点和点击发送验证码,点击登录按钮的时候验证表单。失去焦点的验证直接通过:rules绑定,点击发送验证码的表单验证需要自定义的校验,点击登录时触发表单的submit事件自动进行表单校验。登录成功以后,需要存储token,修改vuex中isLogin,info等信息并进行路由跳转。

11.在进行路由跳转之前,要通过全局路由导航判断跳转页面是否是个人中心,修改个人信息或收藏页。如果是这些页面就要判断是否登录,如果已登录直接跳转,如果未登录则就跳往登录页先登录,不确定是否已登录(比如已登录但是刷新页面isLogin就又为空)则派发请求查看是否登录再进行后续操作。

router.beforeEach(async (to, from, next) => {
    let arr = ['/person', '/updateperson', '/store'];
    if (arr.includes(to.path)) {
        // 检验是否已登录 
        let isLogin = store.state.isLogin;
        // 已登录
        if (isLogin) {
            next();
        }
        // 未登录
        if (isLogin == false) {
            next('/login');
            showToast("小主,请您先登录");
        }
        // 不确定是否已登录
        if (isLogin === null) {
            try {
                let { code, data } = await api.checkLogin();
                if (code !== 0) {
                    next('/login');
                    showToast("小主,请您先登录");
                    return;
                }
                store.commit('changeInfo', data);
                store.commit('changeIsLogin', true)
                next();
            } catch (error) { }
            return;
        }

    } else {
        next();
    }
})

12.如果未登录的情况下是从详情页通过点击收藏按钮进入登录页的,则登录成功之后会返回详情页,我们在详情页进行跳转的时候需要带上一个query参数,参数名为from,参数值为detail。从其他页面跳往登录页,成功之后就跳往个人中心。在登录成功进行路由跳转时需要进行判断,代码如下:

  if (route.query.from) {
        router.replace(`/${route.query.from}`);
  } else {
        router.replace("/person");
  }

13.首页头部展示的图片并不是默认的,需要在组件挂载之前查看仓库中islogin和info是否为null,如果是则发请求获取这两个值。通过计算属性计算展示的图片,根据isLogin和info决定展示的图片是默认的还是服务器返回的。如果info值存在,则返回服务器返回的图片,否则展示默认的图片。

 let pic = computed(() => {
      let { isLogin, info } = store.state;
      if (isLogin) return info.pic || timg;
      return timg;
 });

  onBeforeMount(() => {
      let { isLogin, info } = store.state;
      if (isLogin == null) store.dispatch("changeIsLoginAsync");
      if (info === null) store.dispatch("changeInfoAsync");
  });

14.个人中心页,通过计算属性读取仓库中的info并在页面展示,当点击头像会进入个人中心,点击我的收藏跳转到收藏页,点击退出登录,清除token和vuex中存储的数据并进行路由跳转。退出登录代码如下:

// 退出登录
    let logout = () => {
      showToast("小主,您已经安全退出~");
      localStorage.removeItem("token");
      store.commit("changeStoreList", null);
      store.commit("changeIsLogin", null);
      store.commit("changeInfo", null);
      router.replace("/login");
    };

猜你喜欢

转载自blog.csdn.net/weixin_52797317/article/details/129422927
今日推荐