Durante el proceso de desarrollo, se utiliza a menudo Node.js, que utiliza las capacidades proporcionadas por V8 para ampliar las capacidades de JS. En Node.js, podemos usar el módulo de ruta que no existe en JS. Para que estemos más familiarizados con la aplicación, echemos un vistazo ~
La versión de Node.js de este artículo es 16.14.0. Y el código fuente de este artículo proviene de aquí Versión. Espero que después de leer este artículo, sea útil para todos leer el código fuente.
La ruta se utiliza para procesar las rutas de archivos y directorios. Este módulo proporciona algunas funciones de herramientas que son convenientes para que los desarrolladores las desarrollen para ayudarnos a tomar decisiones complejas sobre rutas y mejorar la eficiencia del desarrollo. Por ejemplo:
Configurar alias en el proyecto La configuración del alias nos facilita la referencia de archivos y evita buscar hacia arriba paso a paso.
resamor: { alias: { // __dirname ruta del directorio 'src' donde se encuentra el archivo actual: path.resolve(__dirname, './src'), // proceso.cwd directorio de trabajo actual '@': path.join(process.cwd(), 'src'), }, }
En webpack, la ruta de salida del archivo también se puede generar en la ubicación especificada a través de nuestra propia configuración.
módulo.exportaciones = { entrada: './ruta/a/mi/entrada/archivo.js', producción: { ruta: ruta.resolve(__dirname, 'dist'), nombre de archivo: 'mi-primer-webpack.bundle.js', }, };
O para operaciones de carpeta,
let fs = require("fs"); let ruta = require("ruta"); // Elimina la carpeta let deleDir = (src) => { // Leer la carpeta let Children = fs.readdirSync(src); niños.forEach(elemento => { let childpath = path.join(src, elemento); // Comprobar si el archivo existe let file = fs.statSync(childpath).isFile(); si (archivo) { // Elimina el archivo si existe fs.unlinkSync(childpath) } demás { //Continuar detectando la carpeta deleDir(childpath) } }) // Elimina la carpeta vacía fs.rmdirSync(src) } deleDir("../floor")
comprende brevemente los escenarios de uso de la ruta. A continuación, estudiaremos su mecanismo de ejecución y cómo se implementa en función de su uso.
Cuando se introduce el módulo de ruta y se llama a la función de herramienta de ruta, se ingresará la lógica de procesamiento del módulo nativo.
Utilice la función _load
para utilizar el nombre del módulo que introdujo como ID para determinar que el módulo que se va a cargar es un módulo JS nativo. Después de eso, la función loadNativeModule
se utilizará para utilizar la identificación para encontrar el código ASCII correspondiente de _source
(. la cadena de código fuente que guarda el módulo JS nativo). Los datos se cargan en el módulo JS nativo.
Ejecute el archivo lib/path.js y utilice el proceso para determinar el sistema operativo. Dependiendo del sistema operativo, puede haber un procesamiento diferencial de caracteres operativos en el procesamiento de archivos, pero el método es aproximadamente el mismo después del procesamiento. la persona que llama.
resolve devuelve la ruta absoluta de la ruta actual.
resolve empalma múltiples parámetros en secuencia para generar una nueva ruta absoluta.
resolver(...argumentos) { dejar dispositivo resuelto = ''; dejar cola resuelta = ''; let resueltoAbsoluto = falso; // Detecta parámetros de derecha a izquierda para (let i = args.length - 1; i >= -1; i--) { ... } //Ruta normalizada resolveTail = normalizeString(resolvedTail, !resolvedAbsolute, '\', isPathSeparator); devolución resueltaAbsoluta? `${dispositivo resuelto}\${cola resuelta}` : `${resolvedDevice}${resolvedTail}` || '.'; }
Obtenga la ruta de acuerdo con los parámetros, recorra los parámetros recibidos, comience a empalmar cuando la longitud de los parámetros sea mayor o igual a 0, realice una verificación sin cadenas en la ruta empalmada, si hay algún parámetro que no coincida , throw new ERR_INVALID_ARG_TYPE(name, 'string', value)
, si se cumplen los requisitos, se juzgará la longitud de la ruta. Si hay un valor, se usará += ruta para el siguiente paso.
dejar camino; si (yo >= 0) { ruta = argumentos[i]; // internos/validadores validarString(ruta, 'ruta'); // Si la longitud de la ruta es 0, saltará directamente fuera del bucle for del bloque de código anterior if (path.length === 0) { continuar; } } más si (resolvedDevice.length === 0) { //La longitud del dispositivo resuelto es 0, asigna el valor a la ruta como directorio de trabajo actual ruta = proceso.cwd(); } demás { // Asigne el valor al objeto de entorno o la ruta del directorio de trabajo actual = Process.env[`=${resolvedDevice}`] || si (ruta === indefinido || (StringPrototypeToLowerCase(StringPrototypeSlice(ruta, 0, 2))!== StringPrototypeToLowerCase (dispositivo resuelto) && StringPrototypeCharCodeAt(ruta, 2) === CHAR_BACKWARD_SLASH)) { // Juzga la ruta a rutas absolutas y no vacías para obtener la ruta path = `${resolvedDevice}\`; } }
Intente hacer coincidir la ruta raíz, determine si solo hay un separador de ruta ('') o si la ruta es una ruta absoluta, luego marque la ruta absoluta y establezca rootEnd
en 1 (subíndice). Si el segundo elemento sigue siendo un separador de ruta (''), defina el valor de intercepción como 2 (subíndice) y use last
para guardar el valor de intercepción para un juicio posterior.
Continúe para determinar si el tercer elemento es un separador de ruta (''). Si es así, es una ruta absoluta y el identificador de intercepción rootEnd
es 1 (subíndice), pero también puede ser una ruta UNC (servernamesharename). , nombre del servidor nombre del servidor nombre compartido nombre del recurso compartido). Si hay otros valores, el valor interceptado continuará incrementándose y leyendo los siguientes valores, y usará firstPart
para guardar el valor del tercer bit para que el valor se pueda obtener al empalmar el directorio y mantener el último valor interceptado. consistente para poner fin a la sentencia.
const len = ruta.longitud; let rootEnd = 0 // Subíndice final de intercepción de ruta let device = ''; // Raíz del disco D:, C: let isAbsolute = false // Si es la ruta raíz del disco const code = StringPrototypeCharCodeAt(path, 0); // la longitud del camino es 1 si (len === 1) { // Sólo hay un separador de ruta para la ruta absoluta if (isPathSeparator(code)) { extremo raíz = 1; esAbsoluto = verdadero; } } más si (isPathSeparator(código)) { // Podría ser una raíz UNC, comenzando con un delimitador , al menos uno de los cuales es algún tipo de ruta absoluta (UNC u otra) esAbsoluto = verdadero; // Comience a hacer coincidir el separador de doble ruta if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) { sea j = 2; dejar durar = j; // Coincide con uno o más delimitadores que no son de ruta mientras (j < len && !isPathSeparator(StringPrototypeCharCodeAt(ruta, j))) { j++; } si (j < len && j !== último) { const primeraParte = StringPrototypeSlice(ruta, último, j); último = j; // Coincide con uno o más separadores de ruta mientras (j < len && isPathSeparator(StringPrototypeCharCodeAt(ruta, j))) { j++; } si (j < len && j !== último) { último = j; mientras (j < len && !isPathSeparator(StringPrototypeCharCodeAt(ruta, j))) { j++; } if (j === len || j !== último) { dispositivo = `\\${primeraParte}\${StringPrototypeSlice(ruta, último, j)}`; raízEnd = j; } } } } demás { extremo raíz = 1; } // Detectar directorio raíz del disco que coincida con el ejemplo: D:, C: } else if (isWindowsDeviceRoot(código) && StringPrototypeCharCodeAt(ruta, 1) === CHAR_COLON) { dispositivo = StringPrototypeSlice(ruta, 0, 2); extremo raíz = 2; if (len > 2 && isPathSeparator(StringPrototypeCharCodeAt(ruta, 2))) { esAbsoluto = verdadero; extremo raíz = 3; } }
Detecte la ruta y generela, verifique si el directorio raíz del disco existe o resuelva si resolvedAbsolute
es una ruta absoluta.
//Detecta el directorio raíz del disco si (device.length > 0) { // dispositivo resuelto tiene valor si (dispositivo resuelto.length > 0) { si (StringPrototypeToLowerCase(dispositivo)!== StringPrototypeToLowerCase (dispositivo resuelto)) continuar; } demás { // dispositivo resuelto no tiene valor y se le asigna el valor del directorio raíz del disco dispositivo resuelto = dispositivo; } } // Ruta absoluta si (resueltoAbsoluto) { // Hay un bucle final si el directorio raíz del disco existe (resolvedDevice.length > 0) romper; } demás { // Obtener el prefijo de ruta para empalmar resolveTail = `${StringPrototypeSlice(ruta, rootEnd)}\${resolvedTail}`; resueltoAbsoluto = esAbsoluto; if (isAbsolute && resolveDevice.length > 0) { // El bucle finaliza cuando existe la raíz del disco break; } }
join realiza empalme de ruta en función de los fragmentos de ruta entrantes
Reciba múltiples parámetros, use separadores específicos como delimitadores para conectar todos los parámetros de la ruta y genere una nueva ruta normalizada.
Después de recibir los parámetros, verifíquelos. Si no hay parámetros, devolverá '.' directamente. De lo contrario, atravesará y verificará cada parámetro a través del método validateString
integrado. Si hay alguna infracción, throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
join
función del carácter de escape es que cuando se usa solo, se considera que escapa de la cadena después de la barra, por lo que se usan barras invertidas dobles para escapar de la barra invertida ('').
Finalmente, la cadena concatenada se verifica y se devuelve en formato.
si (args. longitud === 0) devolver '.'; dejar unido; dejar primeroParte; // Detecta parámetros de izquierda a derecha para (let i = 0; i < args.length; ++i) { argumento constante = argumentos[i]; // internos/validadores validarString(arg, 'ruta'); si (longitud del argumento > 0) { si (se unió === indefinido) // Asigna la primera cadena a unida y usa la variable firstPart para guardar la primera cadena para usarla más adelante join = firstPart = arg; demás // unido tiene un valor, realiza += operación de empalme unido += `\${arg}`; } } si (se unió === indefinido) return '.';
En el sistema de ventanas, se requiere el procesamiento de la ruta de red debido al uso de barra invertida ('') y ruta UNC (que se refiere principalmente al nombre completo de los recursos de Windows 2000 en la LAN), ('') representa es un formato de ruta de red, por lo que el método join
montado en win32 interceptará de forma predeterminada.
Si coincide una barra invertida (''), slashCount
se incrementará. Siempre que coincidan más de dos barras invertidas (''), la ruta empalmada se interceptará y se unirá y escapará manualmente. '').
let necesitaReemplazar = verdadero; deja que slashCount = 0; // Extrae el código de la primera cadena en secuencia de acuerdo con StringPrototypeCharCodeAt y lo relaciona con el código definido mediante el método isPathSeparator if (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 0))) { ++barraContar; const primeraLen = primeraParte.longitud; si (primeroLen > 1 && isPathSeparator(StringPrototypeCharCodeAt(primeraParte, 1))) { ++barraContar; si (primeroLen > 2) { si (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 2))) ++barraContar; demás { necesitaReemplazar = falso; } } } } si (necesitaReemplazar) { mientras (barraCount < unido.longitud && isPathSeparator(StringPrototypeCharCodeAt(unido, slashCount))) { barra diagonalCount++; } si (barraCount >= 2) unido = `\${StringPrototypeSlice(unido, slashCount)}`; }
Clasificación de resultados de ejecución
resolver | la unión | |
---|---|---|
no tiene parámetros | . | La ruta absoluta del archivo actual | .
absoluta | ||
del | archivo actual se empalma | en orden. |
empalma en la ruta absoluta de | rutas no absolutas posteriores. | El|
parámetro posterior de la ruta es un | parámetro de ruta absoluta que sobrescribe la ruta absoluta del archivo actual y sobrescribe | la ruta empalmada por el. | parámetros previos
El primer parámetro es (./) | y tiene parámetros posteriores. El parámetro de empalme de ruta absoluta del archivo actual no tiene parámetros posteriores. La ruta absoluta del archivo actual es La ruta | tiene parámetros posteriores y la ruta empalmada. por los parámetros posteriores no tiene parámetros posteriores (./) |
El parámetro posterior tiene (./) | El parámetro de empalme de ruta absoluta analizado | tiene parámetros posteriores La ruta empalmada no tiene parámetros posteriores, y el empalme (/) |
El. El primer parámetro es (../) | y hay parámetros posteriores. Los parámetros de empalme después del directorio de último nivel que cubre la ruta absoluta del archivo actual no tienen parámetros posteriores. El directorio de último nivel que cubre la ruta absoluta del archivo actual | tiene parámetros posteriores. Empalme No hay parámetros posteriores para los parámetros posteriores (../) |
El parámetro posterior tiene (../ | )Se sobrescribirá el directorio de nivel superior donde aparece (../). Se sobrescribirá el directorio de nivel superior. Después, regrese (/), los parámetros posteriores se unirán y | se sobrescribirá el directorio superior que aparece (../). Después de sobrescribir el directorio superior, se leerá el |
. Después del código fuente, el método resolve
procesará los parámetros, considerará la forma de la ruta y descartará la ruta absoluta al final. Al usarlo, si está realizando operaciones como archivos, se recomienda utilizar el método resolve
. En comparación, el método resolve
devolverá una ruta incluso si no hay parámetros para que el usuario opere, y la ruta se procesará. durante el proceso de ejecución. El método join
solo realiza un empalme estandarizado de los parámetros entrantes, lo cual es más práctico para generar una nueva ruta y puede crearse según los deseos del usuario. Sin embargo, cada método tiene sus ventajas. Debe elegir el método adecuado según sus propios escenarios de uso y necesidades del proyecto.