electron版本升级的简单步骤

 更新时间:2024年05月22日 10:39:25   作者:liyu_ya  
Electron是一款流行的跨平台框架,用于构建桌面应用程序,它基于Web技术栈,结合了Chromium和Node.js,可以使用HTML、CSS和JavaScript开发跨平台的应用程序,本文将介绍electron版本升级的简单步骤,并提供相应的源代码示例,需要的朋友可以参考下

electron-updater使用指南

基础

检测是否最新版

autoUpdater.checkForUpdates()

下载最新版

autoUpdater.downloadUpdate()

项目使用

update.js

const { ipcMain } = require('electron')
const { autoUpdater } = require('electron-updater')
const path = require("path")
// 更新地址,该地址下放的是安装包和latest.yml
const updateURL = 'https://jkcgy.obs.cn-south-1.myhuaweicloud.com/desktop/'
 
 
const message = {
  error: '软件更新异常,请重试',
  checking: '正在检查更新',
  updateAva: '检测到新版本,准备下载',
  updateDown: '软件下载中,请耐心等待',
  updateSet: '下载完成,准备安装',
  updateNotAva: '已经是最新版本',
}
 
//软件版本更新
ipcMain.handle('on-soft-update', (e) => {
  autoUpdater.checkForUpdates()
})
ipcMain.on("updateDesktop", () => {
  console.log("checkForUpdates");
  autoUpdater.checkForUpdates()
  // console.log("downloadUpdate");
 
})
ipcMain.on("updateDesktopping", () => {
  autoUpdater.downloadUpdate()
})
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
function handleUpdate(mainWindow, callback) {
  // 设置是否自动下载,默认是true,当点击检测到新版本时,会自动下载安装包,所以设置为false
  autoUpdater.autoDownload = false
 
  // 如果安装包下载好了,当应用退出后是否自动安装更新
  autoUpdater.autoInstallOnAppQuit = false
  if (process.env.NODE_ENV == "development") {
    autoUpdater.updateConfigPath = path.join(__dirname, "../../aaa/app-update.yml");
 
  }
  // 设置版本更新服务器地址
  autoUpdater.setFeedURL(updateURL)
 
  // 更新发生错误时触发
  autoUpdater.on('error', function () {
    console.log(" 更新发生错误时触发",);
    sendUpdateMessage(message.error, "error")
  })
 
  // 开始检查更新事件
  autoUpdater.on('checking-for-update', function () {
    console.log(" 开始检查更新事件",);
    sendUpdateMessage(message.checking, "checking")
  })
 
  // 没有可更新版本
  autoUpdater.on('update-not-available', function (info) {
    console.log(" 开始检查更新事件",);
    sendUpdateMessage(message.updateNotAva, "updateNotAva")
  })
 
  // 发现可更新版本
  autoUpdater.on('update-available', function (info) {
    console.log(" 发现可更新版本",);
    // autoUpdater.downloadUpdate()
    sendUpdateMessage(message.updateAva, "updateAva")
  })
 
  // 更新下载进度事件
 
  autoUpdater.on('download-progress', function (progressObj) {
    console.log(" 更新下载进度事件",);
    sendUpdateMessage(message.updateDown, "updateDown")
    mainWindow.webContents.send('on-soft-download', progressObj.percent)
  })
 
  // 下载监听
  autoUpdater.on(
    'update-downloaded',
    function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
      mainWindow.webContents.send('on-soft-download', 100)
      sendUpdateMessage(message.updateSet, "updateSet")
      //3秒后更新
      setTimeout(() => {
        autoUpdater.quitAndInstall()
      }, 3000)
    }
  )
 
  // 向渲染进程发送消息
  function sendUpdateMessage(text, type) {
    mainWindow.webContents.send('on-soft-message', text, type)
  }
}
 
module.exports = {
  handleUpdate,
}

然后再 main.js 调用即可

  mainWindow.on('ready-to-show', () => {
    mainWindow.show();
    updater.handleUpdate(mainWindow)
    if (!ipc) ipc = new IPC(mainWindow);
    mainWindow.openDevTools();
    // if(!callWindowIpc) callWindowIpc = new CallWindowIpc(mainInstance);
  });

main.js 所有代码

const { app, BrowserWindow, ipcMain, globalShortcut, Tray, Menu } = require('electron');
const Store = require('electron-store');
const CaptureView = require('./electron-captureview/main/captureview').default;
const path = require('path');
const url = require('url');
const TimMain = require('im_electron_sdk/dist/main');
const { SDK_APP_ID, GET_FILE_INFO_CALLBACK, SCREENSHOTMAC } = require('./const/const');
const IPC = require('./ipc');
const CallWindowIpc = require('./callWindowIpc');
const child_process = require('child_process')
const fs = require('fs')
const updater= require("./update")
const store = new Store();
Store.initRenderer();
const { autoUpdater } = require('electron-updater')
 
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
 
let callWindowIpc;
let ipc;
let mainInstance;
let catchedSdkAppId;
const settingConfig = store.get('setting-config');
const sdkappid = catchedSdkAppId = settingConfig?.sdkappId ?? SDK_APP_ID;
 
let tray = null  // 在外面创建tray变量,防止被自动删除,导致图标自动消失
 
 
const initTimMain = (appid) => {
  mainInstance = new TimMain({
    sdkappid: Number(appid)
  });
}
 
initTimMain(sdkappid);
 
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
 
ipcMain.handle('re-create-main-instance', async (event, newSdkAppid) => {
  console.log("************ re-create-main-instance", newSdkAppid)
  mainInstance.setSDKAPPID(newSdkAppid)
  return
})
 
 
// This allows TypeScript to pick up the magic constant that's auto-generated by Forge's Webpack
// plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
// whether you're running in development or production).
// declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
 
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
// app.on('window-all-closed', function () {
//   if (process.platform !== 'darwin') app.quit()
// })
 
const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    height: 628,
    width: 975,
    minWidth: 975,
    minHeight: 628,
    // show:false,
    icon: path.resolve(__dirname, "../../icon/logo.png"),
    frame: false,
    webPreferences: {
      webSecurity: true,
      nodeIntegration: true,
      nodeIntegrationInWorker: true,
      enableRemoteModule: true,
      contextIsolation: false,
    }
  });
  mainInstance.enable(mainWindow.webContents)
  global.WIN = mainWindow;
 
  mainWindow.on('ready-to-show', () => {
    mainWindow.show();
 
    updater.handleUpdate(mainWindow)
    
 
    if (!ipc) ipc = new IPC(mainWindow);
    mainWindow.openDevTools();
    // if(!callWindowIpc) callWindowIpc = new CallWindowIpc(mainInstance);
  });
  mainWindow.on('close', (e) => {
    // mainWindow.webContents.send('updateHistoryMessage');
    // setTimeout(() => {
 
    //   app.exit();
    // }, 30);
    e.preventDefault();  // 阻止退出程序
    mainWindow.setSkipTaskbar(true)   // 取消任务栏显示
    mainWindow.hide();    // 隐藏主程序窗口
 
  });
  console.log('======process env======', process.env?.NODE_ENV);
  if (process.env?.NODE_ENV?.trim() === 'development') {
    mainWindow.loadURL(`http://localhost:3000`);
    mainWindow.webContents.openDevTools();
  } else {
    mainWindow.loadURL(
      url.format({
        pathname: path.join(__dirname, '../../bundle/index.html'),
        protocol: 'file:',
        slashes: true
      })
    );
  }
 
  // 创建任务栏图标
  tray = new Tray(path.join(__dirname, "../../icon/logo.png"))
 
  // 自定义托盘图标的内容菜单
  const contextMenu = Menu.buildFromTemplate([
    {
      // 点击退出菜单退出程序
      label: '退出', click: function () {
        mainWindow.webContents.send('updateHistoryMessage');
        setTimeout(() => {
          app.exit();
        }, 30);
        // mainWindow.destroy()
      }
    }
  ])
 
  tray.setToolTip('君凯智管')  // 设置鼠标指针在托盘图标上悬停时显示的文本
  tray.setContextMenu(contextMenu)  // 设置图标的内容菜单
  // 点击托盘图标,显示主窗口
  tray.on("click", () => {
    mainWindow.show();
    mainWindow.setSkipTaskbar(false)   // 取消任务栏显示
  })
 
 
  // const capture = new CaptureView({
  //   devTools: false,
  //   Mosaic: false,
  //   Text: false,
  //   // onShow: () => {
  //   //   console.log('start screenshot');
  //   // },
  //   onClose: () => {
  //    const png = clipboard.readImage().toBitmap();
  //    const fileExample = new File([png], 'xxx.png', { type: 'image/jpeg' });
  //     console.log('结束截图', fileExample);
  //   },
  //   onShowByShortCut: () => {
  //     console.log('shortcut key to start screenshot')
  //   }
  // });
  // capture.setMultiScreen(true);
  // capture.updateShortCutKey('shift+option+c');
  globalShortcut.register('Shift+CommandOrControl+C', function () {
    console.log("i am shortcut~~~~~~~~~");
    const newdate = new Date();
    const date = newdate.toISOString().replaceAll(":", "");
    // console.log(date.toISOString());
    if (process.platform == "darwin") {
      let ex = "screencapture -i ~/desktop/screenshot" + date + ".png"
      child_process.exec(`screencapture -i ~/desktop/screenshot` + date + `.png`, (error, stdout, stderr) => {
        if (!error) {
          var _img = fs.readFileSync(process.env.HOME + "/desktop/screenshot" + date + ".png");
          // console.log(_img);
          mainWindow.webContents.send(GET_FILE_INFO_CALLBACK, {
            triggerType: SCREENSHOTMAC,
            data: { _img: _img, date }
          })
        }
      });
    } else {
      let url = path.resolve(__dirname, "../Snipaste-2.8.2-Beta-x64/Snipaste.exe");
      let command = url + " snip -o C:\\Users\\Public\\Desktop\\screenshot" + date + ".png";
      // console.log(command);
      var id = setInterval(dealFile, 300);
      child_process.exec(command, async (error, stdout, stderr) => {
        if (!error) {
          console.log("done capture");
        }
      })
      function dealFile() {
        try {
          var _img = fs.readFileSync("C:\\Users\\Public\\Desktop\\screenshot" + date + ".png");
          clearInterval(id);
          console.log("file exists");
          console.log(_img);
          event.reply(GET_FILE_INFO_CALLBACK, {
            triggerType: SCREENSHOTMAC,
            data: { _img: _img, date }
          })
        } catch (err) {
          if (err.code == 'ENOENT') {
            // console.log("file doesn't exist yet")
          } else {
            throw err;
          }
        }
 
 
      }
    }
 
  })
  // mainWindow.loadURL(`http://localhost:3000`);
  // mainWindow.webContents.openDevTools();
};
 
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
 
Object.defineProperty(app, 'isPackaged', {
  get() {
    return true;
  }
});
 
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  console.log('all-window-closed');
  if (process.platform !== 'darwin') {
    app.exit();
  }
});
 
app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});
 
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.

常见错误指南

Electron更新报错-Skip checkForUpdates because application is not packed and dev update config is not forced

原因是在本地启动的不是安装导致的,在根中配置即可

const { app, BrowserWindow, ipcMain, globalShortcut, Tray, Menu } = require('electron');
 
Object.defineProperty(app, 'isPackaged', {
  get() {
    return true;
  }
});

Electron更新报错-

必须设置这个内容

  "publish": [
      {
        "provider": "generic",
        "channel": "latest",
        "url": "https://jkcgy.obs.cn-south-1.myhuaweicloud.com/desktop/%E5%90%9B%E5%87%AF%E6%99%BA%E7%AE%A1%20Setup%200.0.2.exe"
      }
    ],

Electron更新报错-UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open '****\app-update.yml'
找不到app-update.yml 文件,可以去打包路径中的 dist\win-unpacked\resources 复制,然后通过修改  autoUpdater.updateConfigPath 路径 

 该路径是自定义的路径,自己在 dist\win-unpacked\resources 复制的

const { autoUpdater } = require('electron-updater') 
 autoUpdater.updateConfigPath = path.join(__dirname, "../../aaa/app-update.yml");

Electron更新报错-找不到latest.yml 文件

找不到latest.yml文件 可以去dist 复制

这里跟配置的 autoUpdater.setFeedURL 路径有关系

const { autoUpdater } = require('electron-updater')
const updateURL = 'https://jkcgy.obs.cn-south-1.myhuaweicloud.com/desktop/'
 // 设置版本更新服务器地址
autoUpdater.setFeedURL(updateURL)

拓展:更新electron的版本

方式1

首先,查看electron的版本

electron -v

发现版本为1.4.13

我们输入如下的cmd来查看 electron系列版本

npm view electron versions

可供更新的版本有如下[部分截图]:

完整可供下载的版本如下:

[
  '0.1.0',
  '0.1.1',
  '0.1.2',
  '0.2.0',
  '0.2.1',
  '0.3.0',
  '0.4.0',
  '0.4.1',
  '1.3.1',
  '1.3.2',
  '1.3.3',
  '1.3.4',
  '1.3.5',
  '1.3.6',
  '1.3.7',
  '1.3.8',
  '1.3.9',
  '1.3.10',
  '1.3.12',
  '1.3.13',
  '1.3.14',
  '1.3.15',
  '1.4.0',
  '1.4.1',
  '1.4.2',
  '1.4.3',
  '1.4.4',
  '1.4.5',
  '1.4.6',
  '1.4.7',
  '1.4.8',
  '1.4.10',
  '1.4.11',
  '1.4.12',
  '1.4.13',
  '1.4.14',
  '1.4.15',
  '1.4.16',
  '1.5.0',
  '1.5.1',
  '1.6.0',
  '1.6.1',
  '1.6.2',
  '1.6.3',
  '1.6.4',
  '1.6.5',
  '1.6.6',
  '1.6.7',
  '1.6.8',
  '1.6.9',
  '1.6.10',
  '1.6.11',
  '1.6.12',
  '1.6.13',
  '1.6.14',
  '1.6.15',
  '1.6.16',
  '1.6.17',
  '1.6.18',
  '1.7.0',
  '1.7.1',
  '1.7.2',
  '1.7.3',
  '1.7.4',
  '1.7.5',
  '1.7.6',
  '1.7.7',
  '1.7.8',
  '1.7.9',
  '1.7.10',
  '1.7.11',
  '1.7.12',
  '1.7.13',
  '1.7.14',
  '1.7.15',
  '1.7.16',
  '1.8.1',
  '1.8.2-beta.1',
  '1.8.2-beta.2',
  '1.8.2-beta.3',
  '1.8.2-beta.4',
  '1.8.2-beta.5',
  '1.8.2',
  '1.8.3',
  '1.8.4',
  '1.8.5',
  '1.8.6',
  '1.8.7',
  '1.8.8',
  '2.0.0-beta.1',
  '2.0.0-beta.2',
  '2.0.0-beta.3',
  '2.0.0-beta.4',
  '2.0.0-beta.5',
  '2.0.0-beta.6',
  '2.0.0-beta.7',
  '2.0.0-beta.8',
  '2.0.0',
  '2.0.1',
  '2.0.2',
  '2.0.3',
  '2.0.4',
  '2.0.5',
  '2.0.6',
  '2.0.7',
  '2.0.8-nightly.20180819',
  '2.0.8-nightly.20180820',
  '2.0.8',
  '2.0.9',
  '2.0.10',
  '2.0.11',
  '2.0.12',
  '2.0.13',
  '2.0.14',
  '2.0.15',
  '2.0.16',
  '2.0.17',
  '2.0.18',
  '2.1.0-unsupported.20180809',
  '3.0.0-beta.1',
  '3.0.0-beta.2',
  '3.0.0-beta.3',
  '3.0.0-beta.4',
  '3.0.0-beta.5',
  '3.0.0-beta.6',
  '3.0.0-beta.7',
  '3.0.0-beta.8',
  '3.0.0-beta.9',
  '3.0.0-beta.10',
  '3.0.0-beta.11',
  '3.0.0-beta.12',
  '3.0.0-beta.13',
  '3.0.0-nightly.20180818',
  '3.0.0-nightly.20180821',
  '3.0.0-nightly.20180904',
  '3.0.0',
  '3.0.1',
  '3.0.2',
  '3.0.3',
  '3.0.4',
  '3.0.5',
  '3.0.6',
  '3.0.7',
  '3.0.8',
  '3.0.9',
  '3.0.10',
  '3.0.11',
  '3.0.12',
  '3.0.13',
  '3.0.14',
  '3.0.15',
  '3.0.16',
  '3.1.0-beta.1',
  '3.1.0-beta.2',
  '3.1.0-beta.3',
  '3.1.0-beta.4',
  '3.1.0-beta.5',
  '3.1.0',
  '3.1.1',
  '3.1.2',
  '3.1.3',
  '3.1.4',
  '3.1.5',
  '3.1.6',
  '3.1.7',
  '3.1.8',
  '3.1.9',
  '3.1.10',
  '3.1.11',
  '3.1.12',
  '3.1.13',
  '4.0.0-beta.1',
  '4.0.0-beta.2',
  '4.0.0-beta.3',
  '4.0.0-beta.4',
  '4.0.0-beta.5',
  '4.0.0-beta.6',
  '4.0.0-beta.7',
  '4.0.0-beta.8',
  '4.0.0-beta.9',
  '4.0.0-beta.10',
  '4.0.0-beta.11',
  '4.0.0-nightly.20180816',
  '4.0.0-nightly.20180817',
  '4.0.0-nightly.20180819',
  '4.0.0-nightly.20180821',
  '4.0.0-nightly.20180929',
  '4.0.0-nightly.20181006',
  '4.0.0-nightly.20181010',
  '4.0.0',
  '4.0.1',
  '4.0.2',
  '4.0.3',
  '4.0.4',
  '4.0.5',
  '4.0.6',
  '4.0.7',
  '4.0.8',
  '4.1.0',
  '4.1.1',
  '4.1.2',
  '4.1.3',
  '4.1.4',
  '4.1.5',
  '4.2.0',
  '4.2.1',
  '4.2.2',
  '4.2.3',
  '4.2.4',
  '4.2.5',
  '4.2.6',
  '4.2.7',
  '4.2.8',
  '4.2.9',
  '4.2.10',
  '4.2.11',
  '4.2.12',
  '5.0.0-beta.1',
  '5.0.0-beta.2',
  '5.0.0-beta.3',
  '5.0.0-beta.4',
  '5.0.0-beta.5',
  '5.0.0-beta.6',
  '5.0.0-beta.7',
  '5.0.0-beta.8',
  '5.0.0-beta.9',
  '5.0.0',
  '5.0.1',
  '5.0.2',
  '5.0.3',
  '5.0.4',
  '5.0.5',
  '5.0.6',
  '5.0.7',
  '5.0.8',
  '5.0.9',
  '5.0.10',
  '5.0.11',
  '5.0.12',
  '5.0.13',
  '6.0.0-beta.1',
  '6.0.0-beta.2',
  '6.0.0-beta.3',
  '6.0.0-beta.4',
  '6.0.0-beta.5',
  '6.0.0-beta.6',
  '6.0.0-beta.7',
  '6.0.0-beta.8',
  '6.0.0-beta.9',
  '6.0.0-beta.10',
  '6.0.0-beta.11',
  '6.0.0-beta.12',
  '6.0.0-beta.13',
  '6.0.0-beta.14',
  '6.0.0-beta.15',
  '6.0.0',
  '6.0.1',
  '6.0.2',
  '6.0.3',
  '6.0.4',
  '6.0.5',
  '6.0.6',
  '6.0.7',
  '6.0.8',
  '6.0.9',
  '6.0.10',
  '6.0.11',
  '6.0.12',
  '6.1.0',
  '6.1.1',
  '6.1.2',
  '6.1.3',
  '6.1.4',
  '6.1.5',
  '6.1.6',
  '6.1.7',
  '6.1.8',
  '6.1.9',
  '6.1.10',
  '6.1.11',
  '6.1.12',
  '7.0.0-beta.1',
  '7.0.0-beta.2',
  '7.0.0-beta.3',
  '7.0.0-beta.4',
  '7.0.0-beta.5',
  '7.0.0-beta.6',
  '7.0.0-beta.7',
  '7.0.0',
  '7.0.1',
  '7.1.0',
  '7.1.1',
  '7.1.2',
  '7.1.3',
  '7.1.4',
  '7.1.5',
  '7.1.6',
  '7.1.7',
  '7.1.8',
  '7.1.9',
  '7.1.10',
  '7.1.11',
  '7.1.12',
  '7.1.13',
  '7.1.14',
  '7.2.0',
  '7.2.1',
  '7.2.2',
  '7.2.3',
  '7.2.4',
  '7.3.0',
  '8.0.0-beta.1',
  '8.0.0-beta.2',
  '8.0.0-beta.3',
  '8.0.0-beta.4',
  '8.0.0-beta.5',
  '8.0.0-beta.6',
  '8.0.0-beta.7',
  '8.0.0-beta.8',
  '8.0.0-beta.9',
  '8.0.0',
  '8.0.1',
  '8.0.2',
  '8.0.3',
  '8.1.0',
  '8.1.1',
  '8.2.0',
  '8.2.1',
  '8.2.2',
  '8.2.3',
  '8.2.4',
  '8.2.5',
  '8.3.0',
  '9.0.0-beta.1',
  '9.0.0-beta.2',
  '9.0.0-beta.3',
  '9.0.0-beta.4',
  '9.0.0-beta.5',
  '9.0.0-beta.6',
  '9.0.0-beta.7',
  '9.0.0-beta.9',
  '9.0.0-beta.10',
  '9.0.0-beta.12',
  '9.0.0-beta.13',
  '9.0.0-beta.14',
  '9.0.0-beta.15',
  '9.0.0-beta.16',
  '9.0.0-beta.17',
  '9.0.0-beta.18',
  '9.0.0-beta.19',
  '9.0.0-beta.20',
  '9.0.0-beta.21',
  '9.0.0-beta.22',
  '9.0.0-beta.24',
  '9.0.0',
  '10.0.0-beta.1'
]

接下来,我们使用如下命令卸载原来的electron:

npm uninstall -g electron

使用安装electron的命令:

npm uninstall -g electron

[选] 如果出现如上图所示,说明是文件夹没删干净。这时候我们需要去删除对应文件夹,它这里提示该路径文件还存在。

'C:\Users\xiaoc\AppData\Roaming\npm\node_modules\electron\cli.js

输入win + r, 输入

%AppData%

在该文件夹下 找到 npm,点进去

把该目录下的文件全删了。在 cmd中重新执行

npm install -g electron@v6.1.7

@后面跟随的是版本号,具体可以更新的版本号在上面所示。

这样就表示已经安装完毕。
接下来查看版本

已经更新到想要的版本了.

方式二 :官网

官网方法

以上就是electron版本升级的简单步骤的详细内容,更多关于electron版本升级的资料请关注脚本之家其它相关文章!

相关文章

  • TypeScript中类型映射的使用

    TypeScript中类型映射的使用

    TypeScript中的映射类型和数学中的映射类似,能够将一个集合的元素转换为新集合的元素,本文就来介绍一下TypeScript中类型映射的使用,感兴趣的可以了解一下
    2023-10-10
  • layui 实现二级弹窗弹出之后 关闭一级弹窗的方法

    layui 实现二级弹窗弹出之后 关闭一级弹窗的方法

    今天小编就为大家分享一篇layui 实现二级弹窗弹出之后 关闭一级弹窗的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • vscode使用Prettier Code插件的详细教程

    vscode使用Prettier Code插件的详细教程

    这篇文章主要介绍了vscode使用Prettier Code插件的详细教程,本文通过图文实例相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • 微信小程序Echarts覆盖正常组件问题解决

    微信小程序Echarts覆盖正常组件问题解决

    这篇文章主要介绍了微信小程序Echarts覆盖正常组件问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • js禁止浏览器页面后退功能的实例(推荐)

    js禁止浏览器页面后退功能的实例(推荐)

    下面小编就为大家带来一篇js禁止浏览器页面后退功能的实例(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 微信小程序实现页面左右滑动

    微信小程序实现页面左右滑动

    这篇文章主要为大家详细介绍了微信小程序实现页面左右滑动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • javascript实现避免页面按钮重复提交

    javascript实现避免页面按钮重复提交

    很多时候我们都需要防止重复提交,这方面的文章也比较多,实现的途径差别也很大.因为有些时候即使服务器能够识别重复的提交,也会造成问题.比如需要很长等待时间的操作,在首次提交后,不断重复提交,页面可能会死掉.用脚本来控制的话可以防止这种问题.
    2015-01-01
  • 建议大家看下JavaScript重要知识更新

    建议大家看下JavaScript重要知识更新

    建议大家看下JavaScript重要知识更新...
    2007-07-07
  • JavaScript中的null和undefined解析

    JavaScript中的null和undefined解析

    在JavaScript开发中,被人问到:null与undefined到底有啥区别? 一时间不好回答,特别是undefined,因为这涉及到undefined的实现原理
    2012-04-04
  • JS仿QQ好友列表展开、收缩功能(第二篇)

    JS仿QQ好友列表展开、收缩功能(第二篇)

    这篇文章主要介绍了JS仿QQ好友列表展开、收缩功能,当点击一个li元素,其他li元素上的类名清除掉。代码简单易懂,需要的朋友可以参考下
    2017-07-07

最新评论