每月进步一点点--202308

838 阅读14分钟

36. yarn build 构建遇到的错误消息 - Error EPERM operation not permitted,xxx 如何解决?

最后查明,这是因为项目下的dist/assets中的某个文件被cosbrowser软件占用着,重新打包的时候,无法覆盖同名文件。只要关闭占用dist/assets目录下的软件,打包就正常了。

35. 如何避免被代码补全工具坑?

如下代码片段,代码补全工具给我提示的Ant-Design-Vue的TreeSelect组件,设置默认展开项的属性值是 defaultExpandedKeys,结果我赋值之后,发现没有效果。然后在网上看了许多旁门左道的方法,试了一下都没用。最后查看了一下官方文档,发现是属性值写错了,正确的属性值应该是treeDefaultExpandedKeys, 结结实实被坑了一把。这件事情对我的启发是:如果发现设置的属性值无效,先去官方文档看看正确的使用方法,看的时候要细心,不然还是会因为粗心大意而对错误视而不见,如果发现自己严格遵照着官方文档书写使用,效果还是不对,再去寻找其它的方法。

<a-tree-select
    showSearch
    :tree-default-expand-all="maxLevel ? false : true"
    :placeholder="placeholder || '请选择或者搜索特定部门'"
    :filterTreeNode="filterTreeNode"
    :dropdownStyle="{ height: '200px' }"
    v-model:value="treeValues"
    :maxTagCount="maxTagCount ?? 10"
    tree-checkable
    allow-clear
    :defaultExpandedKeys="defaultExpandedKeys"
    @change="handleChange"
  />

34. 如何减少缓存给调试带来的烦恼?

背景是: 有个管理平台,退出功能之前没做好,每次登陆超时之后,需要手动修改页面的url地址,刷新页面,进行重新登录。在此种条件下,发生了奇怪的事情,每次部署新功能后,没看到效果,人肯定会去刷新页面,然而当登陆超时时,手动将页面地址改成登陆地址,刷新页面,页面居然展示的是之前的页面功能,没有最新的页面功能,而且打包出来的js和css文件,文件名中都含有hash信息,为何每次刷新页面的时候,加载的不是最新的资源。造成接口返回了新菜单,也页面新菜单的资源未加载到,造成每次会展示404页面。我发现按住Ctrl+F5两次,可以解决这个问题。但缓存的问题时有时无,所以有时候出现了缓存问题,人也想不到那方面去。对于浅显的缓存问题,人还是容易辨别,在复杂场景下,出现缓存问题,人解决起来就会绕一大圈弯路。我的做法是,如果本地是正常的,而部署后出问题,先清缓存,排除一下缓存的干扰。

33. vite proxy如何打印出真实的转发地址?

在vite的proxy对象中,添加一个bypass选项,打印出真实的转发地址,或者将真实的转发地址设置在响应头中。

    proxy: {
        [process.env.VITE_API_PATH as string]: {
          target: process.env.VITE_API_HOST,
          changeOrigin: true,
          secure: false,
          rewrite: (path) => path.replace(/^\/api/, ''),
          bypass: (req, res, options) => {
            const proxyUrl = `${options.target}${options.rewrite?.(req.url as string)}`;
            console.log(proxyUrl);
            res.setHeader('x-res-proxyUrl', proxyUrl);
          },
        },
      },

image.png

32. Stylelint: Invalid value "consecutive-duplicates-with-different-syntaxes" for option "ignore" of rule "declaration-block-no-duplicate-properties" 解决方法?

提示consecutive-duplicates-with-different-syntaxes这个属性是无效的,查看了一下stylelint的官方文档,发现这是stylelint-v15.5.0才有的属性,而项目中使用的stylelint版本是14.3.0, 肯定没有这个属性。

image.png

然后在node_modules/stylelint-config-recommended/index.js找到如下配置:

image.png

说明stylelint-config-recommended的版本太高了, 那么解决这个问题的思路就很明确了

image.png

要么升级stylelint到更高版本,要么降低stylelint-config-recommended的版本, 还有一种改法,就是在.stylelintrc.js中覆盖这条规则

  rules: {
    'declaration-block-no-duplicate-properties': [true],
 }

31. 为什么说判断条件的书写顺序很重要?

如下代码,业务逻辑没变更前,判断条件是这样写的:authentication的取值是0或1。

    const { authentication} = detail;

    if (authentication === 1) {
      removeAuth();
    }else if (authentication === 0) {
      queryCustNo();
    } 

业务逻辑变更后,authType的正常的取值范围1,2,3,4, 如果用authType !== 4去判断是否需要调用解除绑定接口,就会出错,因为原本要执行authentication=0逻辑的场景, 也同时符合authType !== 4的判断条件,而因为authType !== 4判断条件写在前面,所以会被先执行,导致逻辑出错。

    const { authentication, mobile = '', custNo = '' ,authType} = detail;

    // 
    if (authentication === 4 || authType !== 4) {
      removeAuth();
    }else if (authentication === 0) {
      queryCustNo();
    }  

正确的逻辑应该是:

    const { authentication, mobile = '', custNo = '' ,authType} = detail;

    if (authentication === 0) {
      queryCustNo();
    } 
    else if (authentication === 4 || authType !== 4) {
      removeAuth();
    }

30. The engine "node" is incompatible with this module如何解决?

在本地构建好好的项目,当使用Jenkins进行打包发布时,出现了一个报错。使用yarn安装项目的依赖包,错误如下:

image.png

查看了一下@yarnpkg/parsers@3.0.0-rc.49的包的package.json 文件的engines配置,找到了问题所在:因为当前node的版本是16.13.2,而这个包要求node的版本大于18.12.0,所以引起安装错误。

image.png

解决方法是在package.json中用resolutions字段指定依赖的依赖版本。

  "resolutions": {
    "@yarnpkg/parsers": "3.0.0-rc.48.1"
  }

另外这里有个大坑, 直接点击Jenkins工作空间下的文件(下图的红框位置)打开的内容可能存在缓存,看到的内容不正确,正确的打开姿势是点击右侧的查看按钮。

image.png

29. 沟通工作问题时如何减少反复沟通?

  • 把问题汇总,一次性说完
  • 细心理解,用大白话表达。
  • 根据岗位特点,使用对方好理解的方式沟通
  • 控制沟通时间和节奏,保持较高的信息密度

28. 外网如何访问局域网中的内网机器?

  1. 首先要在外网电脑上安装vpn软件,运行并登录vpn软件
  2. 其次要关闭外网电脑上的防火墙
  1. 获取要连接机器的IP地址,这样就能访问到内网机器的服务了

27. vite打包时出现警告 build.terserOptions is specified but build.minify is not set to use Terser. Note Vite now defaults to use esbuild for minification. If you still prefer Terser, set build.minify to "terser".,如何解决?

这句话说vite默认使用esbuild进行代码压缩,如果配置了build.terserOptions对象,要将minify的值修改为terser

    minify: 'terser',
      // 可以小幅提高压缩率,减小大文件体积
      terserOptions: {
        compress: {
          keep_infinity: true,
          drop_console: false,
          drop_debugger: true,
        },
        format: {
          comments: false, // 删除注释
        },
      },

26. node-gyp rebuild引起的控制台错误,如何解决?

这个问题是由安装一个tree-sitter-json的npm包引起的,tree-sitter-json用到了node-gpy,node-gyp的主要作用是编译原生 C++ 模块,解决模块的跨平台问题,看网上的说法是node-gyp和电脑上已经安装的python 版本和 Visual studio 版本不匹配, 参考此文,不过我采用的另外一种解决方法,我用pnpm替换yarn安装了一下项目依赖,整个过程并没有出现告警。

image.png

25.项目启动不了,出现大量同样的报错信息如下所示:[vite] Failed to load source map for /node_modules/.vite/deps/ant-design-vue_es_avatar_style_css.js.map, 如何解决?

看提示是Vite加载缓存的依赖失败了,查看了一下项目下的node_modules/.vite文件夹,发现什么文件也没有,最奇怪的是,启动项目之后,也不生成缓存文件。在网上查了半天,只看到有人描述这个问题,可是没有解决方案。最后自己升级了一下vite,vite-plugin-style-import,ant-design-vue,问题得到解决。

image.png

image.png

升级前:

  import styleImport from "vite-plugin-style-import";

  // 按需加载样式文件
  styleImport({
    libs: [
      {
        libraryName: "ant-design-vue",
        esModule: true,
        resolveStyle: (name) => {
          return `ant-design-vue/es/${name}/style/index`;
        },
      },
    ],
  });

升级后:

  // 按需加载UI组件样式,vite 自带按需加载仅针对js
  import { createStyleImportPlugin, AndDesignVueResolve } from "vite-plugin-style-import";

  // 按需加载样式文件
  createStyleImportPlugin({
    resolves: [AndDesignVueResolve()],
  });

24. Window下的Linux子系统,报错rm: cannot remove dir-name: Directory not empty如何解决?

出现这个错误,是由于系统正在使用打算删除文件夹中的可执行程序,一般重启Linux系统就可解决。 启动方法是:以管理员身份,打开终端,输入如下目录:

#停止LxssManager服务
net stop LxssManager  
 
#启动LxssManager服务
net start LxssManager  

然后再执行下面的删除命令,你发现一切就正常了

rm -rf dir-name

23. Linux下如何生成和解压zip文件?

如果机器上没有安装zip压缩包软件,要先用yum指令进行安装

yum install zip

假设要压缩pnpm_demo文件夹下的所有内容,用zip指令压缩pnpm_demo文件夹下的所有内容,生成压缩包pnpm_offline.zip的指令为:

cd pnpm_demo && zip -q -r pnpm_offline.zip *

把压缩包上传到另外一个机器之后,进行解压的命令为:

unzip -d /pnpm_offline pnpm_offline.zip

22. 如何离线全局安装npm包?

首先你得找和服务器一样的操作系统机器,安装npm-pack-all工具,制作离线安装的tgz包

npm install -g npm-pack-all

查看已全局安装的npm包位置,这里以nx为例

which nx

image.png

进入全局npm安装位置

cd /mnt/c/Program\ Files/nodejs/node_modules/nx

在nx目录下执行npm-pack-all,生成安装的tgz包

npm-pack-all

把生成的tar包,上传到内网机器, 执行安装操作

npm install  nx-16.13.2.tgz

打开环境变量配置文件,环境变量配置文件一般路径是/root/.bashrc

vi ~/.bashrc

在最后一行添加所要设置的环境变量

export PATH=/上面nx安装之后bin文件夹路径:$PATH

执行source命令,环境变量立即生效

source ~/.bashrc

21. Jenkins打包构建,控制台每行都输出Permission denied是什么原因?

image.png

这是因为没有给打包构建输出目录夹赋予写入权限,查看文件夹权限的命令是

ls -l 文件夹

image.png

  • 第一位代表文件类型,有两个数值:“d”和“-”,“d”代表目录,“-”代表非目录。

  • 后面9位可以拆分为3组来看,分别对应不同用户:

2-4位代表所有者user的权限说明,5-7位代表组群group的权限说明,8-10位代表其他人other的权限说明。

  • r代表可读权限,w代表可写权限,x代表可执行权限。

给文件夹的所有者,组群,其它人递归赋予读,写,执行权限的命令是:

chmod -r 777 文件夹

chown命令也可以解决问题:

  • chownchange owner的含义(更改所有者),
  • -R 选项表示连同子目录中的所有文件,一并修改
  • 所有者:所属组 同时更改所有者和所属组
chown user:root -R  demo文件夹

20. 管理后台--时间段选择框宽度设置成自适应,会出现什么问题?

管理后台,列表查询表单,大多采用栅格布局,将一行分为24等份, 如果对栅格布局使用不当,就会出现如下的情况,在屏幕比较窄的PC机器上,长一点的时间段选择器选择的时间会显示不全,如下图所示:

image.png

我想到的处理方式就是给时间段选择器设置一个最小宽度,为了展示美观,可以给所有的栅格容器,都设置一个最小宽度,这样就兼顾了上下排列整齐和屏幕太小选择日期被遮挡问题

19. 页面一片空白的排查思路?

  1. 查看网页资源加载路径是否正确
  2. 查看控制台日志,js脚本有无报错
  3. 查看登陆授权接口是否报错或返回结果有误
  4. 查看静态服务器的nginx配置是否正确
  5. 如果后端存在登陆重定向页面地址逻辑,而在前端找不到任何线索,那就需要后端看看登陆重定向逻辑。

18. /bin/sh: nx:command not found 如何解决?

如下图所示, 提示在/bin/sh下,找不到nx命令

image.png

解决方法是全局安装nx

npm install -g @nrwl/cli

如果安装完之后还有问题,可用这个命令查看 npm 放置全局安装包的路径

npm config get prefix

可参考此文,用export PATH指令设置Linux系统下的环境变量。

17. 给一个div设置了上下左右四个方向负的margin值,表现有什么不同?

左边和上边设置了负的margin值比较好理解,是当前元素向左或向上偏移

<div class="container">
  <div class="left"></div>
</div>

<style>
.container {
  width: 10rem;
  height: 10rem;
  border: 1px solid #666666;
  margin: 100px auto;
  .left {
    width: 3.125rem;
    height: 3.125rem;
    background-color: #ffcc66;
    opacity: 0.8;
    /* margin-left: -20px; */
    margin-top: -20px;
  }
}
</style>

而右边或下边设置了负的外边距,情况就不太一样了,对当前元素不会产生任何影响,移动的效果体现在当前元素右侧或下侧紧邻的元素上。

<div class="container">
	<div class="left"></div>
	<div class="right"></div>
</div>

<style>
.container{
  width: 10rem;
	height: 10rem;
	border: 1px solid #666666;
	margin: 100px auto;
  /* display:flex; */

  .left,
  .right{
    width: 3.125rem;
    height: 3.125rem;
  }
  
  .left{
    opacity: 0.8;
    background-color: green;
    margin-bottom: -20px;
  }
        
  .right{
    opacity: 0.5;
    background-color: #333;
  }
}
</style>

16. 一台机器,要通过正向代理访问外网指定资源,这个指定的资源文件应该放在那台服务器上,才能被访问?

这是正向代理配置,正向代理有三个特征:

  1. 不能有hostname。
  2. 必须有resolver, 即dns,即下面的114.114.114.114
  3. 正向代理参数,均是由 Nginx 变量组成。
server {
	listen                           80;
	server_name                      localhost;
	resolver                         114.114.114.114;
	proxy_connect;
	proxy_connect_allow              443 80;
	proxy_connect_connect_timeout    10s;
	proxy_connect_read_timeout       10s;
	proxy_coneect_send_timeout       10s;
	location / {
          proxy_pass $scheme://$http_host$request_uri;
	}
}

这是目标服务器配置,应该把要访问的证书文件,配置在目标服务器,才能被访问到。

location /zT8d0hxWrk.txt{
  alias /你的服务器根路径/cert/zT8d0hxWrk.txt;
}

15. [Vue warn]: Component inside renders non-element root node that cannot be animated. 解决方法?

这种路由写法:

  <router-view v-slot="{ Component, route }">
    <transition>
      <keep-alive :include="keepAliveList">
        <component :is="Component" />
      </keep-alive>
    </transition>
  </router-view>

当页面没有被根元素包裹时,会提示没有根节点时,<Transition>组件无法渲染动画。

image.png

解决方法有三种:

  1. 在警告提示的页面,添加根元素
  2. 在全局路由处,添加根元素, 但这种修改方式,会让页面多出两级嵌套的div
  <router-view v-slot="{ Component, route }">
    <transition>
     <div :key="route.fullPath">
      <keep-alive :include="keepAliveList">
        <component :is="Component" />
      </keep-alive>
     </div>
    </transition>
  </router-view>

image.png

  1. 移除路由过渡动画效果, 路由切换过渡动画属于锦上添花,去除了也没关系
  <router-view v-slot="{ Component, route }">
      <keep-alive :include="keepAliveList">
        <component :is="Component" />
      </keep-alive>
  </router-view>

14. 发送短信验证码按钮需要做的UI优化

  • 发现很多网站及应用,发送短信验证码按钮宽度会随文字长短变化,如果设置了圆角,按钮宽度变短了,按钮完全变了样,看着比较丑陋

image.png

  • 比较好的做法是保持短信验证码按钮宽度固定

image.png

13. 循环中的判断优化的一个小技巧分享

把大概率会命中的判断条件放在前面,不太容易命中的放在后面

  const arr = Array.from(Array(10), (item, index)=>index);
  arr.forEach((item, index)=>{
    if(index !== 4){
      // do something
    }else{
      // do else
    }
  })

12. vue的template中,父组件传入的属性,在引用的时候,是否可以省略props?

常规写法:

<div :style="props.gridStyle.backgroundFrameImg && `background-image: url(${props.gridStyle.backgroundFrameImg})`">

偷懒写法,在template中用到props属性时,可以省略

<div :style="gridStyle.backgroundFrameImg && `background-image: url(${gridStyle.backgroundFrameImg})`">

11. 前端有没有可以加解密的算法库?

项目中要实现一个加解密功能,要js-md5加解密算法的话,只能加密,不能解密。那么前端领域,有没有对称的加解密库,在网上找了一下,找到了crypto-js,测试了一下,知道加密字符串的情况下,可以解密加密之后的字符。测试用例如下:

 import CryptoJS from 'crypto-js';

  // 密钥一致才能进行解密
  const aseKey = 'hello,crypto!!!!';
  // 原始字符串
  const encrpytText = 'abc12345';
  // 加密之后的字符串
  const decryptText = 'NplXcmyLdw6AikuQ7hBUGA==';
  //调用加密方法
  console.log(cryptoEncryption(aseKey, encrpytText));
  //调用解密方法
  console.log(cryptoDecrypt(aseKey, decryptText));

  // crypto-js加密
  // aseKey为密钥(必须为:8/16/32位),message为要加密的密文
  function cryptoEncryption(aseKey, message) {
    var encrypt = CryptoJS.AES.encrypt(message, CryptoJS.enc.Utf8.parse(aseKey), {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    }).toString();
    return encrypt;
  }
  // crypto-js解密
  function cryptoDecrypt(aseKey, message) {
    var decrypt = CryptoJS.AES.decrypt(message, CryptoJS.enc.Utf8.parse(aseKey), {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    }).toString(CryptoJS.enc.Utf8);
    return decrypt;
  }

另外一种选择就是用base64加解密,效果也不错

import {encode, decode } from 'js-base64';
const str='hello-base64';
const enctryStr=encode(str);
console.log( enctryStr, decode(enctryStr) );

10. 动态加载图片时,发现第一次会出现资源请求报错,是什么原因引起的?

如下图所示, 抓包发现,出现一个undefined的图片加载请求,不知道从哪里发出的, 经过一番排查,终于找到了元凶。是因为页面中有张背景图片,值是通过接口获取的,刚开始时背景图片未设置初始值,可是浏览器也发起了资源加载请求,于是就出现了一个undefined的图片资源加载错误。

image.png

所以加载的图片如果是通过接口获取的,那么要判断一下,这个图片资源是否为空,如果不为空,才去加载。

错误写法:

<div :style="`background-image: url(${props.gridStyle.backgroundFrameImg})`">

正确写法:

<div :style="props.gridStyle.backgroundFrameImg && `background-image: url(${props.gridStyle.backgroundFrameImg})`">

9.vue3 style中的css变量, 如果是个对象,该如何书写?

直接这样写,会提示错误

 background-color: v-bind(props.gridStyle.prizeUnderpainting);

正确写法:

 background-color: v-bind('props.gridStyle.prizeUnderpainting');

8.ts中如何设置泛型默认的类型定义?

首先给网络请求方法request添加一个泛型定义

 export default function request<T = { [key: string]: any }>
  apiConfig: Apis.IApiProps,
  params: Apis.IReqParams = {},
  options: Apis.IOptionsParams = {}
): Promise<Apis.IResDataProps<T>>

重点来了,在这里给泛型设置一个默认值

 // 请求返回类型
  type IResDataProps<T> = {
    // 业务代码
    ret: number;
    // 业务数据
    retdata: T;
    // 业务消息
    retmsg: string;
  };

在接口定义的地方,用具体属性定义替代泛型。

  getActivityInfo: (params: Apis.IReqParams) => {
    const apiConfig: Apis.IApiProps = {
      method: 'GET',
      url: '/url/xxx/xxx',
    };
    return request<ILotteryProps>(apiConfig, params);
  },

另外在使用的地方,不能这样写,这样写retdata的类型是ILotteryProps | {}

 http.getActivityInfo({}).then(({ retdata={} }) => {

应该这样写,retdata的类型才是ILotteryProps

http.getActivityInfo({}).then(({ retdata }) => {

7.ts定义了对象类型之后,如何避免还要把对象的每个属性都初始化一次?

如果这样写, 会提示{}缺少很多属性

 const activityInfo = ref<ILotteryProps>({});

这样写才是正确的姿势

 // 活动信息
  const activityInfo = ref({} as ILotteryProps);

6. v-text/v-html 提示 will override element children的原因是什么?

是因为标签中还有其它内容, 即使是注释也不行。需要删除干净

错误写法:

<div v-html="content">
 <!-- 里面有注释也会引起告警 -->
</div>

正确写法:

 <!-- 里面有注释也会引起告警 -->
<div v-html="content">
</div>

5. rem在个别IOS机型上,展示效果不正常,如何解决?

image.png

rem的动态计算方法如下:

  (function (doc, win) {
    var docEl = doc.documentElement,
      resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
      recalc = function () {
        var clientWidth = docEl.clientWidth;
        clientWidth > 750 && (clientWidth = 750),
          clientWidth < 375 && (clientWidth = 375),
          //                    if (!clientWidth) return;
          (docEl.style.fontSize = 100 * (clientWidth / 750) * (window.devicePixelRatio || 1) + 'px');
      };

    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false);
  })(document, window);

rem单位在计算的时候,可能不是整数,如果一个元素尺寸是 0.625px,那么其染尺寸应该是 1px,空出的 0.375px 空间由其临近的元素填充;同样道理,如果一个元素尺寸是 0.375px,其渲染尺寸就应该是 0,但是其会占据临近元素 0.375px 的空间。这样就会造成用rem设置的宽度,前半部分长一些表现的效果就是部分文字被遮挡,最朴素的处理思路就是对个别误差表现明显的地方,给rem单位后面多加几位小数,参考此文

4. 在企业微信中,打开H5自建应用,报证书不可信的错误,怎么解决?

有三种可能:

  1. 证书确实出了问题问题,比如说过期了,一般这种可能性比较小
  2. 当时那段时间网络不好,多刷新几次页面
  3. 三是之前访问时错误的页面也被缓存下来,而且通过刷新页面的情况缓存无用。需要深度清除缓存,错误的要通过高级功能==>通用==>存储空间的方式来清理,如果还不行,就用手机管理--清理加速功能来清理。

3. 评估工时总是心里没底,如何破解?

有这个困惑的人,不是不知道要开发的业务的详细流程步骤,不清楚具体要做哪些事情;就是不知道功能的实现方案,开发时间是多久。这就要求我们,除了花时间敲代码,也要抽出时间,熟悉业务流程,尤其是那些比较繁琐的业务流程。第二,要记录自己开发每项功能的开发用时,要完整的记录各个阶段的开发耗时,从需求理解,到UI实现,到编码开发,到联调测试,到提测,以及这个过程中对需求含糊不清,有遗漏的地方的沟通确认时间,对测试提的一些缺陷,感觉有分歧,有歧义的沟通时间,把这些时间加起来,就是开发一个业务功能的必要时间。

  • 前端评估工时按照 页面开发(结构+表现)+页面交互(行为)+接口联调 三部分去评估
  • 需求+技术实现方案明确 按必要工时*1去评估
  • 需求不明确+技术实现方案明确 按必要工时*1.2去评估
  • 需求明确+技术实现方案不明确 按必要工时*1.5去评估
  • 需求+技术实现方案都不明确 按必要工时*2去评估
  • 平时要记录自己的工作任务耗时, 需求细节沟通花费了多长时间+开发编码花费了多长时间+缺陷修复花费了多少时间(按正常情况统计,先不考虑意外情况比如说需求变更, UI设计稿太毛糙导致返工,后端主流程接口阻塞,开发过程中评审会议很多, 历史功能出现棘手的bug得优先处理等等)

2. 站点换肤方案,该如何选?

页面站点换肤,大体说来,有两种方案,一是给需要换肤的地方,添加一个换肤类; 二是通过定义css变量的方式,通过js代码修改换肤的css变量颜色。第一种是在多处要添加换肤样式判断逻辑,第二种是一次性设置到位,第二种效率更高,更易维护。

1. 如下的代码,会引发什么问题?

下面的代码,是实现一个下拉加载更多的功能。每次请求分页数据的过程中,会展示loading动画。这种实现方式会造成一个bug, 每次分页数据请求结束后,分页列表会滚动到列表第一条所在位置。而且这个问题还比较隐蔽。只有在部分机型上才有。究其原因,是因为loading展示设置不合理,不应该在loading动画结束后,重新渲染列表数据,应该改成要么在列表上方悬浮一个loading动画,要么在列表最下方展示loading动画。

<template>
  <Loading v-if="isLoading" />
  <--! 分页列表组件 -->
  <ScrollList v-else />
</template>