前端开发经验总结(持续更新...)

一、获取到数据再渲染组件,否则显示正在加载

1、添加一个加载状态:使用一个 ref 来表示是否已加载数据。

const loading = ref(true); // 添加一个加载状态

2、更新加载状态:在数据获取成功后,将 loading 状态修改为 false

async function fetchmemberStyleList() {
    try {
      console.log("获取会员风采列表数据");
      const res = await memberStyleApi.getmemberStyleList();
      memberStyles.value = res.data;
      console.log("memberStyles", memberStyles.value);
      loading.value = false; // 数据获取成功,更新加载状态
    } catch (error) {
      console.log("获取会员风采列表数据失败");
      loading.value = false; // 如果获取失败,仍然更新加载状态
    }
}

3、在模板中使用条件渲染:通过 v-if 控制组件的渲染。

<div v-if="loading">正在加载...</div>
<a-card class="affiliateCard" title="会员风采" v-if="!loading">
    <template #extra>
        <a href="#">更多 <RightOutlined /></a>
    </template>
    <div class="affiliateCard-list">
        <a-card hoverable class="affiliateCard-item" v-for="item in memberStyles" :key="item.id" :headStyle="cardHeadStyle">
            <template #cover>
                <img alt="example" src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png" />
            </template>
            <a-card-meta :title="item.name" class="ant-card-meta-title">
                <template #description>{{ item.introduction }}</template>
            </a-card-meta>
        </a-card>
    </div>
</a-card>

二、一些字符串处理方法

// string String

let str = "Hello world"; // 字符数组
console.log(str.length); // 11, 不是方法,是属性
console.log(str.charAt(1)); // e  获得某个位置的字符
console.log(str[1]); // 等价于 str.charAt(1)

// 字符串方法
console.log(str.toUpperCase()); // HELLO WORLD
console.log(str.toLowerCase()); // hello world

// 查找子串
console.log(str.indexOf("l")); // 2 查找子串的位置,没有返回-1
console.log(str.lastIndexOf("l")); // 9 同上,从右边开始查找 >=0说明有
console.log(str.includes("o w")); // true 是否包含子串
console.log(str.startsWith("Hel")); // true 是否以某个子串开头
console.log(str.endsWith("rld")); // true 是否以某个子串结尾

// 获取子串
console.log(str.substring(4, 7)); // o w 截取子串[start, end-1],子串长度=end-start
console.log(str.substring(4)); // o world 从start截取到末尾
console.log(str.slice(-5)); // world 从后往前截取,负数表示从末尾开始算起
console.log(" str ".trim()); // str,去掉首尾空格"


console.log(str.replace("l", "L")); // HeLLo world
console.log(str.slice(2, 5)); // llo 截取子串,不包含5

三、then 方法(在异步函数成功完成并返回结果后执行

根据参数获取不同栏目的文章赋值给对应的数组

//  ================ 获取文章数据 ======================
async function fetchEssayInfo(type,columnTitle) {
  try {
    console.log("获取文章数据");
    const res = await essayApi.getessayInfo(type,columnTitle);
    console.log("获取文章数据成功",res.data);
  }
  catch (error) {
    console.log("获取文章数据失败");
  }
}
//学会动态文章列表
const associationDynamicDates = fetchEssayInfo('学会动态');
fetchEssayInfo('学会动态').then(res => {
  console.log("学会动态文章列表",res.data);
  associationDynamicDates.value = res.data;
});

// 通知公告文章列表
const noticeDates = ref([]);
fetchEssayInfo('通知公告').then(res => {
  console.log("通知公告文章列表",res.data);
  noticeDates.value = res.data;
});

四、列表分页请求

1、完整代码

<template>
  <div class="card-wrapper">
    <a-card :headStyle="headStyle">
      <template #title>
        <span style="margin-right: 8px"><AimOutlined /></span>当前位置:<a href="/">首页 > </a><a href="">{{ props.param }}</a>
      </template>
      <!-- 列表 -->
      <a-list bordered :data-source="Dates" :pagination="pagination" class="card-content">
        <template #renderItem="{ item }">
          <a-list-item>
            <router-link :to="`/viewNews/${item.id}`">
              {{ item.textTitle }} <RightOutlined />
            </router-link>
            <span class="item-date">{{ item.createdTime }}</span>
          </a-list-item>
        </template>
      </a-list>
    </a-card>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';
import { defineProps } from 'vue';
import { essayApi } from '/@/api/essay';

// 接收父组件传来的 param 和 selectedType
const props = defineProps({
  param: {
    type: String, 
    required: true
  },
  selectedType: {
    type: String, 
    required: true,
  }
});

// 使用 param
console.log('右边接收到的参数:', props.param);
console.log("所选文章类型:", props.selectedType);

const emit = defineEmits(['update:modelValue']);

// 卡片样式
const headStyle = {
  color: '#108ee9',
  fontSize: '13px',
  height: '20px',
  lineHeight: '20px',
  padding: '0 15px',
  background: '#f5f7f9',
  borderBottom: '1px solid #e8e8e8',
};

// 分页配置
const pageNum = ref(1);
const pageSize = ref(6);
const total = ref(0); // 存储总记录数

// 使用 reactive 来确保 pagination 是响应式的
const pagination = ref({
  current: pageNum.value,
  pageSize: pageSize.value,
  total: total.value,
  onChange: (page) => {
    pageNum.value = page;
    // 更新 pagination.current
    pagination.value.current = page;
    if (props.selectedType === '全部') {
    fetchEssayInfo(pageNum.value, pageSize.value, null, null, props.param, null, ); 
  } else {
    fetchEssayInfo(pageNum.value, pageSize.value, null, null, props.param, props.selectedType ); 
  }
  },
});

// 文章列表
const Dates = ref([]);

async function fetchEssayInfo( currentPage = 1, currentSize = 6,searchCount = null ,sortItemList = null ,columnTitle, type,) {
  try {
    console.log("获取文章数据");
    const res = await essayApi.getessayInfo(currentPage, currentSize, searchCount, sortItemList, columnTitle, type);
    console.log("获取文章列表数据成功", res.data);
    Dates.value = res.data.list; // 假设返回的数据格式中包含一个 list 数组
    total.value = res.data.total; // 假设返回的数据中包含总记录数
    // 更新 pagination.total 和 pagination.current
    pagination.value.total = total.value;
    pagination.value.current = currentPage;
    console.log("获取文章数据成功", Dates.value);
  } catch (error) {
    console.log("获取文章数据失败");
  }
}

// 调用函数以加载不同类型的文章数据
fetchEssayInfo(pageNum.value, pageSize.value, null, null, props.param, null ); 

// 监听 param 变化
watch(() => props.param, (newVal) => {
  console.log("监听到 param 变化", newVal);
  if (props.selectedType === '全部') {
    fetchEssayInfo(pageNum.value, pageSize.value, null, null, props.param, null ); 
  } else {
    fetchEssayInfo(pageNum.value, pageSize.value, null, null, props.param, props.selectedType ); 
  }
});

// 监听父组件传来的 selectedType 变化
watch(() => props.selectedType, (newVal) => {
  console.log("监听到 selectedType 变化", newVal);
  if (newVal === '全部') {
    fetchEssayInfo(pageNum.value, pageSize.value, null, null, props.param, null, ); 
  } else {
    fetchEssayInfo(pageNum.value, pageSize.value, null, null, props.param, newVal ); 
  }
});
</script>

<style scoped>
.card-wrapper {
  margin: 15px 15px 0 0;
}
.card-content a {
  color: #333;
  display: block;
  width: 500px;
  overflow: hidden; /*内容会被修剪,并且其余内容是不可见的。*/
  text-overflow: ellipsis; /*显示省略符号来代表被修剪的文本*/
  white-space: nowrap; /*文本不会换行,文本会在同一行上继续。*/
}
.card-content a:hover {
  color: #1890ff;
  text-decoration: underline;
}
.item-date {
  color: #999; /* 日期颜色可以自行调整 */
}
</style>

2、代码解释

  1. 定义分页相关的响应式数据

    • 使用 ref 声明了 pageNum(当前页数)、pageSize(每页记录数)和 total(总记录数),以及一个响应式对象 pagination,用于管理分页相关的状态和行为。

  2. 分页配置

    • pagination 对象中定义了 current(当前页数)、pageSize(每页大小)、total(总记录数)以及 onChange 方法。当用户切换页面时,会调用 onChange 方法(更新页码并重新调用接口)。

  3. 切换页面时的逻辑

    • onChange 方法中,根据当前页数(page)更新 pageNumpagination.current。它会检查选择的文章类型,如果是“全部”,则会调用 fetchEssayInfo 方法获取所有文章;如果是其他类型,则会相应地获取特定类型的文章。

  4. 获取文章信息的异步请求

    • fetchEssayInfo 方法包含了从后端接口获取文章数据的逻辑。根据传入的当前页数和每页记录数,发送请求并更新文章列表 Dates 和总记录数 total

  5. 更新分页信息

    • 通过接口返回的数据更新 pagination.totalpagination.current,确保分页组件能够正确反映当前状态。

  6. 对父组件参数变化的监听

    • 使用 watch 监听 props.paramprops.selectedType 的变化,以便在这些值变更时自动重新获取文章数据。

整体而言,通过上述步骤,页面实现了按页加载文章的功能,用户可通过分页组件进行浏览,点击不同的上下页,页面会根据当前页数与选择的类型重新加载文章列表。


前端开发经验总结(持续更新...)
http://localhost:8090//archives/qian-duan-kai-fa-jing-yan-zong-jie-chi-xu-geng-xin...
作者
cchen
发布于
2024年10月15日
许可协议