简历问题

251 阅读10分钟
  1. 什么是Svg
  2. 常用的动画特效
  3. 数字可视化大屏怎么实现
  4. 地图的openlayers常用的api是什么
  5. webpack的打包过程
  6. vite和Rollup
  7. vue中hooks是什么
  8. 组件版本管理?如何管理
  9. url-loader? 主域并发数是什么
  10. virtualList的实现原理是什么
  11. 静态资源CDN加速?异步加载模块组件?路由懒加载?
  12. FCP是什么
  13. JWT替换传统Session登录
  14. RefreshToken刷新双token形式解决长时间保留token的安全问题
  15. webSocket实时获取后台信息
  16. 切片上传?文件秒传、断电续传、错误重试、控制并发
  17. Treeshaking,Scope Hosting,Gzip
  18. 实现水印?
  19. html2canvas和jspdf解决pdf内容截断问题以及乱码问题
  20. 外抛slot是什么 elementUI?
  21. 防抖和节流
  22. 页面加载完执行一个函数如何实现?
  23. vue中hash和history的区别
  24. vue中localtion.href和router.push啥区别
  25. 自定义指令

1.SVG

是一种用于描述基于二维的矢量图形的XML标记语言。 blog.csdn.net/xzd2333/art…

2.常用的动画特效

1.@keyframes定义动画名称 2.调用动画

@keyframes run {/* 也可使用关键字 "from" 和 "to"(代表 0%(开始)和 100%(完成))*/
    0%{      /* 开始状态 */

    }
    100%{      /* 结束状态 */

    }
}
  • transition 实现渐变动画
  • transform 转变动画
  • animation 实现自定义动画

3.数字可视化大屏

前端自适应解决方案:

  1. 使用flex布局,结合元素百分比
  2. 使用rem单位

大屏自适应的解决方案:transform:scale
大屏使用rem耗时,而且对浏览器最小字体不支持
juejin.cn/post/709044…
juejin.cn/post/709072…

5.webpack打包

  • 初始化参数: 从配置文件和shell 语句中读取与合并参数,得到最终的参数。

  • 开始编译: 用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行 compiler 对象的 run 方法开始执行编译。

  • 确定入口: 根据配置中的 entry 找出所有的入口文件。

  • 编译模块: 从入口文件出发,调用所有配置的 Loader 对模块进行编译,找出该模块依赖的模块,再递归本步骤直到所有依赖文件都经过本步骤的处理。

  • 完成模块编译: 在经过第 4 步使用 Loader 编译完所有模块之后,得到每个模块被编译后的最终内容以及它们之间的依赖关系。

  • 输出资源: 根据入口和模块之间的关系,组装成一个个包含多个模块的 chunk,再把每个 chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。

  • 输出完成: 在确定输出内容之后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
    juejin.cn/post/706680…

6.vite和rollup

webpack常用于应用打包,rollup常用于第三方库打包

7.vue中的hooks

juejin.cn/post/708340…

8.组件版本管理

9.url-loader

url-loader 和 file-loader 的工作方式是相似的,但是可以将较小的文件,转成 base64 的 URI(即以 base64 的方式编码图片文件,这样到时候就不需要单独下载它了 juejin.cn/post/702930…

主域并发数: 服务器能够同时处理的并发请求或链接的数量

10.virtualList的实现原理

主要是利用了 对数据的不断截取,只渲染截取的数据

image.png
如图所示:列表分为可见区域和缓冲区域,超出这个范围的列表 DOM 都将被删除。

11.CDN加速

使用CDN主要解决两个问题:

  1. 打包时间太长、打包后代码体积太大,请求慢
  2. 服务器网络不稳带宽不高,使用cdn可以回避服务器带宽问题 juejin.cn/post/702173…

异步加载模块组件

动态组件:是Vue中一个特殊的Html元素:<component>,它拥有一个特殊的 is 属性,属性值可以是 已注册组件的名称一个组件的选项对象,它是用于不同组件之间进行动态切换的。

异步组件:简单来说是一个概念,一个可以让组件异步加载的方式;它一般会用于性能优化,比如减小首屏加载时间、加载资源大小。

    Vue.component('async-example', function (resolve, reject) {
        setTimeout(function () {
            // 向 `resolve` 回调传递组件定义
            resolve({
                template: '<div>I am async!</div>'
            })
        }, 1000)
    })

路由懒加载就是将路由匹配的组件变为异步组件,异步组件是指只有页面需要用到时才从服务器加载的组件。

通过异步组件和webpacm代码分割,实现路由懒加载,按需加载,提升路由页面加载速度。

juejin.cn/post/698572…

简单来说,写在路由配置文件中的异步加载就是路由懒加载的用法,而写在组件内部的异步加载就是异步组件用法。 www.cnblogs.com/tive/p/1559…

12.FCP是什么

  • load(Onload Event),它代表页面中依赖的所有资源加载完的事件。
  • DCL(DOMContentLoaded),DOM解析完毕。
  • FP(First Paint),表示渲染出第一个像素点。FP一般在HTML解析完成或者解析一部分时候触发。
  • FCP(First Contentful Paint),表示渲染出第一个内容,这里的“内容”可以是文本、图片、canvas。
  • FMP(First Meaningful Paint),首次渲染有意义的内容的时间,“有意义”没有一个标准的定义,FMP的计算方法也很复杂。
  • LCP(largest contentful Paint),最大内容渲染时间。

白屏结束时间 = FP事件触发时间 首屏结束时间 = FCP事件触发时间

13.JWT替换传统Session登录

session登录通常是用户访问服务器生成一个sessionID,储存在服务器中,通时将sessionId传给浏览器,当浏览器再次访问时,http请求就带有sessionId,服务器根据id获取到用户信息 session的缺点是当用户量大时,会占用大量服务器内存,每次客户请求都要向服务器获取sessionId,导致请求速度变慢

现在多采用JWT代替Session,JWT使用JSON来保存令牌信息,并不把信息保存在服务端,而是保存在客户端。JWT的结构包括头部、负载和签名:

头部中保存的是加密算法说明,负载中保存用户信息,签名是根据头部和负责经过算法算出来的值 JWT的登陆流程:

  • 客户端向服务单发送登陆请求
  • 服务端检验用户名密码,如果成功将从数据库中提取出这个用户的Id、角色等信息
  • 服务端采用自定义的秘钥对用户信息(JSON)进行签名,形成签名数据
  • 将用户信息(JSON)和上一步形成的签名拼接形成JWT,发送给客户端
  • 客户端每次请求都带上这个JWT
  • 每次服务器收到带JWT的请求后,使用自定义的秘钥对JWT的签名进行校验,如果成功则从JWT中取出用户信息

14.RefreshToken刷新双token形式解决长时间保留token的安全问题

浏览器向服务器发送请求,返回一个token和refreshToken,浏览器存储到localstrore中。再次发送时,如果校验到401,token失效,前端在请求中拦截,将refreshtoken传给后端,如果refreshtoken没有失效,则返回新的token和refreshtoken,若失效则返回登录页面
解决token时效短,频繁登录认证的问题

15.webSocket实时获取后台信息

使用 WebSocket 实时获取后台信息是一种常见的做法,可以实现双向通信,适用于聊天应用、实时通知、股票报价等场景。下面是一个基本的实现步骤和示例。

1. 后端实现

假设你使用 Node.js 和 ws 库来创建一个 WebSocket 服务器:

// server.js
const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
  console.log('新连接建立');

  // 每隔 1 秒发送一条消息
  const intervalId = setInterval(() => {
    const message = JSON.stringify({ time: new Date().toISOString() });
    ws.send(message);
  }, 1000);

  ws.on('close', () => {
    clearInterval(intervalId);
    console.log('连接关闭');
  });
});

2. 前端实现

在前端,使用 WebSocket API 连接到 WebSocket 服务器,并处理接收到的消息:

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>WebSocket 示例</title>
</head>
<body>
  <h1>实时信息</h1>
  <div id="messages"></div>

  <script>
    const messagesDiv = document.getElementById('messages');
    const socket = new WebSocket('ws://localhost:8080');

    socket.onopen = () => {
      console.log('连接已打开');
    };

    socket.onmessage = (event) => {
      const data = JSON.parse(event.data);
      const message = document.createElement('div');
      message.textContent = `收到信息: ${data.time}`;
      messagesDiv.appendChild(message);
    };

    socket.onclose = () => {
      console.log('连接已关闭');
    };

    socket.onerror = (error) => {
      console.error('WebSocket 错误:', error);
    };
  </script>
</body>
</html>

3. 启动服务器和访问前端

  1. 启动 WebSocket 服务器:

    node server.js
    
  2. 打开浏览器,访问你的 HTML 文件(例如 index.html)。你将看到实时更新的时间信息。

总结

  • 后端 使用 WebSocket 服务器接收和发送消息。
  • 前端 使用 WebSocket API 连接服务器并处理消息。

你可以根据具体需求扩展这个基础示例,比如增加用户身份验证、处理不同类型的消息等。

16.文件分片上传

blog.csdn.net/qq_43040552…

  1. MD5读取文件,获取文件的MD5编码
  2. 请求服务端判断文件是否上传,如上传完成就直接返回文件地址
  3. 如未上传,判断是否是断点续传
  4. 判断是并发上传还是顺序上传
  5. 开始分片文件上传,分片上传完成后写入已上传列表中
  6. 判断是否上传完成

https://juejin.cn/post/6844904046436843527#heading-18

17. Treeshaking,Scope Hosting,Gzip

Treeshaking

Tree Shaking 是一种通过消除未使用的代码来优化打包的技术,主要用于 JavaScript 应用中。它依赖于 ES6 模块系统(import 和 export),能够在构建时分析代码,去除那些没有被引用的部分,从而减小打包后的文件大小。 如何实现

  • 确保使用 ES6 模块语法。
  • 使用支持 Tree Shaking 的打包工具,如 Webpack 和 Rollup。
  • 将 mode 设置为 production(如在 Webpack 中),因为它会自动进行 Tree Shaking。

例子

// utils.js
export const usedFunction = () => {};
export const unusedFunction = () => {};

如果在其他模块中只导入了 usedFunction,则打包时 unusedFunction 会被移除。

Scope Hoisting

Scope Hoisting 是一种优化技术,用于减少 JavaScript 代码的封装层级,提高代码执行效率。在 Webpack 中,Scope Hoisting 通过将多个模块合并为一个函数作用域,从而减少了闭包的数量,降低了执行时的开销。

如何实现

  • 使用 Webpack 的 mode: 'production',因为它会自动启用 Scope Hoisting。
  • 使用 ES6 模块化语法(import 和 export),因为它可以更好地支持 Scope Hoisting。

Gzip

Gzip 是一种文件压缩格式,通常用于减小网页资源的大小,从而加快网页加载速度。服务器在传输 HTML、CSS、JavaScript 等资源时,可以使用 Gzip 对这些文件进行压缩,客户端在接收到这些文件时会自动解压。 如何实现

  • 在服务器上启用 Gzip 压缩。例如,在 Apache 和 Nginx 中,可以通过配置文件轻松开启 Gzip。
  • 确保客户端支持 Gzip,现代浏览器通常都支持。 Nginx 配置示例
gzip on;
gzip_types text/plain application/javascript text/css;
gzip_min_length 1000;

常用配置有:filter(过滤:对哪些文件进行压缩);threshold:1024000 (对大于1mb的文件进行压缩);deleteOriginFile: false(压缩后是否删除源文件)

18.实现水印

第一步还是在页面上覆盖一个固定定位的盒子,然后创建一个canvas画布,绘制出一个水印区域,将这个水印通过toDataURL方法输出为一个图片,将这个图片设置为盒子的背景图,通过backgroud-repeat:repeat;样式实现填满整个屏幕的效果
pointer-events:none解决绝对定位造成点击事件无法穿透的问题

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
</head>

<body>
    <div id="info">
        <div class="box" onclick="console.log('点击到啦')">
            djfdhg ghfjghjg fddfhgj ghfd jkghfjh gfd
            djfdhg ghfjghjg fddfhgj ghfd jkghfjh gf
        </div>
    </div>
    <script>

            function __canvasWM({
                container = document.body,
                width = '300px',
                height = '200px',
                textAlign = 'center',
                textBaseline = 'middle',
                font = "20px Microsoft Yahei",
                fillStyle = 'rgba(184, 184, 184, 0.6)',
                content = '水印',
                rotate = '45',
                zIndex = 10000
            } = {}) {
                const args = arguments[0];
                const canvas = document.createElement('canvas');

                canvas.setAttribute('width', width);
                canvas.setAttribute('height', height);
                const ctx = canvas.getContext("2d");

                ctx.textAlign = textAlign;
                ctx.textBaseline = textBaseline;
                ctx.font = font;
                ctx.fillStyle = fillStyle;
                ctx.rotate(Math.PI / 180 * rotate);
                ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2);

                const base64Url = canvas.toDataURL();
                const __wm = document.querySelector('.__wm');

                const watermarkDiv = __wm || document.createElement("div");
                const styleStr = `
                  position:fixed;
                  top:0;
                  left:0;
                  bottom:0;
                  right:0;
                  width:100%;
                  height:100%;
                  z-index:${zIndex};
                  pointer-events:none;
                  background-repeat:repeat;
                  background-image:url('${base64Url}')`;

                watermarkDiv.setAttribute('style', styleStr);
                watermarkDiv.classList.add('__wm');

                if (!__wm) {
                    container.insertBefore(watermarkDiv, container.firstChild);
                }

                if (typeof module != 'undefined' && module.exports) {  //CMD
                    module.exports = __canvasWM;
                } else if (typeof define == 'function' && define.amd) { // AMD
                    define(function () {
                        return __canvasWM;
                    });
                } else {
                    window.__canvasWM = __canvasWM;
                }

            }
        

        // 调用
        __canvasWM({
            content: '水印8983'
        });
    </script>
</body>

</html>
<style>
    .box{
        width: 600px;
        height: 700px;
    }
</style>

19. html2canvas和jspdf解决pdf内容截断问题以及乱码问题

使用 html2canvas 和 jspdf 生成 PDF 文件时,确实可能会遇到内容截断和乱码的问题。以下是一些常见的解决方案。

1. 内容截断问题

解决方法

  • 设置页面尺寸:确保在创建 PDF 时,页面尺寸与要捕获的内容匹配。可以通过 jspdf 的参数设置页面大小。
const doc = new jsPDF({
  orientation: 'portrait',
  unit: 'mm',
  format: 'a4',
  putOnlyUsedFonts: true,
  floatPrecision: 16 // float precision for higher quality
});
  • 调整 html2canvas 的选项:使用 html2canvas 时,可以通过设置 scrollX 和 scrollY 来确保捕获到完整内容。
html2canvas(document.querySelector("#element"), {
  scrollX: 0,
  scrollY: -window.scrollY,
}).then((canvas) => {
  const imgData = canvas.toDataURL("image/png");
  const imgWidth = 210; // A4 size in mm
  const pageHeight = 295; // A4 size in mm
  const imgHeight = (canvas.height * imgWidth) / canvas.width;
  const heightLeft = imgHeight;

  let position = 0;

  doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
  position += heightLeft;

  if (heightLeft >= pageHeight) {
    doc.addPage();
  }

  doc.save('download.pdf');
});

2. 乱码问题

解决方法

  • 字体支持:确保你使用的字体在 PDF 中是嵌入的。你可以使用 jspdf 提供的 addFont 方法来添加自定义字体。
// 加载字体(例如使用 jsPDF 提供的ttf文件)
const font = "path/to/your/font.ttf"; // 确保字体文件可访问
jsPDF.API.addFileToVFS("CustomFont.ttf", font);
jsPDF.API.addFont("CustomFont.ttf", "CustomFont", "normal");
doc.setFont("CustomFont");
  • 确保编码正确:确保在生成 PDF 时,文本的编码是正确的。可以尝试使用 UTF-8 编码。

示例代码

以下是一个完整的示例,将 html2canvas 和 jspdf 结合使用,解决上述问题:

function generatePDF() {
  const doc = new jsPDF({
    orientation: 'portrait',
    unit: 'mm',
    format: 'a4',
    putOnlyUsedFonts: true,
    floatPrecision: 16,
  });

  html2canvas(document.querySelector("#element"), {
    scrollX: 0,
    scrollY: -window.scrollY,
  }).then((canvas) => {
    const imgData = canvas.toDataURL("image/png");
    const imgWidth = 210; // A4 width in mm
    const pageHeight = 295; // A4 height in mm
    const imgHeight = (canvas.height * imgWidth) / canvas.width;
    const heightLeft = imgHeight;

    let position = 0;

    doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
    position += heightLeft;

    // 分页处理
    while (heightLeft >= pageHeight) {
      position -= pageHeight;
      doc.addPage();
      doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
    }

    doc.save('download.pdf');
  });
}

查看全部

总结

  • 内容截断:确保页面尺寸匹配,适当设置 html2canvas 的选项。
  • 乱码:确保字体支持和文本编码正确。

20.外抛slot是什么 elementUI?

在 Element UI 中,外抛 slot(或称为作用域插槽)是一种特殊的插槽,用于将数据从父组件传递到子组件,以便父组件能够根据子组件提供的上下文动态地渲染内容。这种机制使得组件更加灵活和可复用。

基本概念

  • 插槽:插槽是 Vue 组件中的一种占位符,允许在组件使用时传入自定义内容。
  • 作用域插槽:通过作用域插槽,父组件可以访问子组件中的数据或方法。

使用示例

假设你有一个自定义的表格组件,使用外抛 slot 来实现动态渲染表格行。

1. 子组件(Table.vue)

<template>
  <table>
    <tr v-for="item in items" :key="item.id">
      <slot :item="item"></slot>
    </tr>
  </table>
</template>

<script>
export default {
  props: {
    items: Array
  }
};
</script>

2. 父组件(Parent.vue)

<template>
  <div>
    <Table :items="tableData">
      <template v-slot="{ item }">
        <td>{{ item.name }}</td>
        <td>{{ item.age }}</td>
      </template>
    </Table>
  </div>
</template>

<script>
import Table from './Table.vue';

export default {
  components: { Table },
  data() {
    return {
      tableData: [
        { id: 1, name: 'Alice', age: 25 },
        { id: 2, name: 'Bob', age: 30 }
      ]
    };
  }
};
</script>

查看全部

关键点

  • 在子组件中,使用 <slot :item="item"> 语法将 item 数据传递给插槽。
  • 在父组件中,使用 v-slot 指令来接收这个数据,并自定义如何渲染每一行。

总结

外抛 slot(作用域插槽)在 Element UI 中提供了一种强大的方式来传递数据,使得组件间的互动更加灵活。通过这种方式,开发者可以根据子组件的上下文动态渲染父组件的内容,从而提高代码的复用性和可维护性。

21.防抖和节流

防抖和节流的使用场景

防抖(debounce)

1.search搜索时,用户在不断输入值时,用防抖来节约请求资源。

节流(throttle)

1.鼠标不断点击触发,mousedown(单位时间内只触发一次) 2.监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

如何实现

1.防抖 (多次触发 只执行最后一次)

作用: 高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间内再次触发,则重新计算时间 防抖类似于英雄联盟回城6秒,如果回城中被打断,再次回城需要再等6秒

实现代码:

<body>
    <input type="text" id="inp">
    <script>

        // 1.封装防抖函数
        function debounce(fn, time) {
            // 4.创建一个标记用来存放定时器的返回值
            let timeout = null;
            return function () {
                // 5.每当用户触发input事件  把前一个 setTimeout 清楚掉
                clearTimeout(timeout);
                // 6.然后又创建一个新的 setTimeout, 这样就能保证输入字符后等待的间隔内 还有字符输入的话,就不会执行 setTimeout里面的内容
                timeout = setTimeout(() => {
                    // 7.这里进行防抖的内容
                    fn();
                }, time);
            };
        }

        // 2.获取inpt元素
        var inp = document.getElementById('inp');
    	// 8. 测试防抖临时使用的函数
        function sayHi() {
            console.log('防抖成功');
        }
        // 3.给inp绑定input事件  调用封装的防抖函数  传入要执行的内容与间隔事件 
        inp.addEventListener('input', debounce(sayHi, 5000)); 

    </script>

</body>
2.节流 (规定时间内 只触发一次)

作用: 高频率触发的事件,在指定的单位时间内,只响应第一次 节流类似于英雄联盟里的英雄平A 一定是内点击多次只进行攻击一次

<script>
    // 1.封装节流函数
    function throttle(fn, time) {
        //3. 通过闭包保存一个 "节流阀" 默认为false
        let temp = false;
        return function () {
            //8.触发事件被调用 判断"节流阀" 是否为true  如果为true就直接trurn出去不做任何操作
            if (temp) {
                return;
            } else {
                //4. 如果节流阀为false  立即将节流阀设置为true
                temp = true; //节流阀设置为true
                //5.  开启定时器
                setTimeout(() => {
                    //6. 将外部传入的函数的执行放在setTimeout中
                    fn.apply(this, arguments);
                    //7. 最后在setTimeout执行完毕后再把标记'节流阀'为false(关键)  表示可以执行下一次循环了。当定时器没有执行的时候标记永远是true,在开头被return掉
                    temp = false;
                }, time);
            }
        };
    }
    function sayHi(e) {
        // 打印当前 document 的宽高
        console.log(e.target.innerWidth, e.target.innerHeight);
    }
    // 2.绑定事件,绑定时就调用节流函数  
    // 敲黑板!!! 这里是重点 绑定是就要调用一下封装的节流函数 触发事件是触发封装函数内部的函数
    window.addEventListener('resize', throttle(sayHi, 2000));
</script>

22.页面加载完执行一个函数如何实现

window.onload=function(){
    alert("请参见离职指引");
}
$().ready(function(){ 
    alert("请参见离职指引");
})
定时器

23.vue中hash和history的区别

在 Vue Router 中,hash 和 history 是两种不同的路由模式,各有优缺点。

1). Hash 模式

  • 原理:使用 URL 的 hash 部分(#)来管理路由。例如,URL 会变成 http://example.com/#/home
  • 优点
    • 简单易用,兼容性好,支持旧版浏览器。
    • 不需要服务器配置,直接在客户端处理。
  • 缺点
    • 不支持浏览器的“前进”或“后退”按钮的真正刷新,刷新页面会重新加载整个应用。
    • URL 中的 hash 部分不被搜索引擎索引。

2). History 模式

  • 原理:使用 HTML5 的 History API 来管理路由,例如 URL 会变成 http://example.com/home
  • 优点
    • URL 更加美观、易读,且不包含 #
    • 支持真正的前进和后退,刷新页面时可以保持状态。
    • 更适合搜索引擎优化(SEO)。
  • 缺点
    • 需要服务器支持,以确保所有路由都能返回同一个 HTML 页面。通常需要配置服务器,以处理 404 错误。

总结

选择哪种模式取决于你的应用需求。如果需要简单的路由并兼容旧版浏览器,选择 hash 模式;如果追求更好的用户体验和 SEO,选择 history 模式。

24.vue中localtion.href和router.push啥区别

在 Vue 中,location.href 和 router.push 都可以用于导航,但它们的工作方式和用途有一些重要的区别。

1. location.href

  • 用途:直接改变浏览器的 URL,类似于在浏览器地址栏输入新地址。

  • 特点

    • 导航时会导致整个页面重新加载。
    • 可以跳转到外部 URL。
    • 适用于需要重新加载整个应用或访问外部资源的场景。

2. router.push

  • 用途:用于 Vue Router 实现客户端路由的导航。

  • 特点

    • 不会导致页面重新加载,而是通过 Vue Router 的机制来切换视图。
    • 适合在单页应用中进行导航,保持应用的状态和性能。
    • 支持传递路由参数和查询字符串。

总结

  • 使用场景:如果你在单页应用中需要无缝切换视图,使用 router.push。如果你需要访问外部 URL 或重新加载页面,则使用 location.href
  • 性能router.push 更高效,因为它避免了完整的页面重载,保持了应用的状态。

vue自定义指令

Vue.directive 方法来注册一个全局指令

1. 创建自定义指令

可以通过 Vue.directive 方法来注册一个全局指令,也可以在组件中使用 directives 选项注册局部指令。

全局指令示例
// 在 main.js 或类似的入口文件中
Vue.directive('focus', {
  // 当绑定元素插入到 DOM 中时调用
  inserted: function (el) {
    el.focus();
  }
});
局部指令示例
export default {
  directives: {
    focus: {
      // 当绑定元素插入到 DOM 中时调用
      inserted(el) {
        el.focus();
      }
    }
  }
}

2. 使用自定义指令

在模板中使用自定义指令时,前面加上 v- 前缀。

<template>
  <input v-focus />
</template>

3. 指令钩子函数

自定义指令提供了多个钩子函数,可以在不同的生命周期阶段执行特定操作。常用的钩子函数包括:

  • bind:指令第一次绑定到元素时调用,只会调用一次。
  • inserted:被绑定元素插入父节点时调用。
  • update:所在组件的 VNode 更新时调用,可能会多次调用。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:指令与元素解绑时调用。

示例:一个简单的自定义指令

以下是一个简单的自定义指令示例,用于改变文本颜色:

// 在 main.js 中
Vue.directive('color', {
  // 绑定元素
  bind(el, binding) {
    el.style.color = binding.value; // 设置文本颜色
  }
});

在模板中使用:

<template>
  <div v-color="'red'">这是红色文本</div>
</template>

总结

自定义指令在 Vue 中非常灵活,适用于需要对 DOM 元素进行特殊操作的场景。可以根据需求定义不同的指令和钩子函数,以实现复杂的功能。