02.《Electron 跨平台开发实战》- chapter02-项目bookmark

《Electron 跨平台开发实战》系列

官方源码地址:https://github.com/electron-in-action/
我的源码地址:https://github.com/K-Artisan/electron-in-action-book-note

项目BookMark

源码地址:https://github.com/electron-in-action/bookmarker

界面

项目结构

项目Code解析

package.json

{
  "name": "bookmark",
  "version": "1.0.0",
  "description": "",
  "main": "./app/main.js",
  "scripts": {
    "start": "electron .",
    "test": "echo \"Error:no test specified\" && exit 1"
  },
  "author": "weikai",
  "license": "ISC",
  "dependencies": {
    "electron": "^9.0.3"
  }
}

main.js

const { app, BrowserWindow } = require('electron');
let mainWindow = null; // #A

//app 负责管理Electron应用的生命周期
app.on('ready', () => {
    mainWindow = new BrowserWindow({
        webPreferences: {
            nodeIntegration: true
        }
    }
    );
    mainWindow.loadURL(`${__dirname}/index.html`); // #A
});

要点解析:

__dirname

__dirname变量是当前正被执行的Node应用的完整路径,在笔者的电脑上,这个值是: (略)/bookmark/app

index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link type="text/css" rel="stylesheet" href="styles.css">
    <title>Bookmarker</title>
</head>

<body>
    <h1>Bookmarker</h1>

    <div class="error-message"></div>
    
    <section class="add-new-link">
      <form class="new-link-form">
        <input type="url" class="new-link-url" placeholder="URL" required>
        <input type="submit" class="new-link-submit" value="Submit" disabled>
      </form>
    </section>

    <section class="links"></section>

    <section class="controls">
      <button class="clear-storage">Clear Storage</button>
    </section>


    <script>
        require('./renderer.js');
    </script>
</body>

</html>

renderer.js

const { shell } = require('electron'); //提供与高层级桌面集成有关的函数
const parser = new DOMParser(); //Chrominum提供的文本解析器

const linksSection = document.querySelector('.links');
const errorMessage = document.querySelector('.error-message');
const newLinkForm = document.querySelector('.new-link-form');
const newLinkUrl = document.querySelector('.new-link-url');
const newLinkSubmit = document.querySelector('.new-link-submit');
const clearStorageButton = document.querySelector('.clear-storage');

//监听Url输入框是否有效
newLinkUrl.addEventListener('keyup', () => {
    newLinkSubmit.disabled = !newLinkUrl.validity.valid;
});


newLinkForm.addEventListener('submit', () => {
    event.preventDefault();
    const url = newLinkUrl.value;
    fetch(url)
        .then(validateResponse)
        .then(response => response.text())
        .then(parseResponse)
        .then(findTitle)
        .then(title => storeLink(title, url))
        .then(clearForm)
        .then(renderLinks)
        .catch(error => handleError(error, url));
});

//shell模块:使用用户默认的浏览器打开链接
linksSection.addEventListener('click', (event) => {
    if (event.target.href) {
      event.preventDefault();
      shell.openExternal(event.target.href);
    }
  });

clearStorageButton.addEventListener('click', () => {
    localStorage.clear();
    linksSection.innerHTML = '';
});

const clearForm = () => {
    newLinkUrl.value = null;
}


//将html文本解析成DOM结构树
const parseResponse = (text) => {
    return parser.parseFromString(text, 'text/html');
}

//遍历DOM树找到title节点文本
const findTitle = (nodes) => {
    return nodes.querySelector('title').innerText;
}

//使用内置localStorage存储 url
const storeLink = (title, url) => {
    localStorage.setItem(url, JSON.stringify({ title: title, url: url }));
}


const getLinks = () => {
    debugger
    let ss = Object.keys(localStorage);
    let ess = ss.map(key => JSON.parse(localStorage.getItem(key)));

    return Object.keys(localStorage)
        .map(key => JSON.parse(localStorage.getItem(key)));
}


const convertToElement = (link) => {
    return `<div class="link"><h3>${link.title}</h3>
            <p><a href="${link.url}">${link.url}</a></p></div>`;
}


const renderLinks = () => {
    const linkElements = getLinks().map(convertToElement).join('');
    linksSection.innerHTML = linkElements;
}


const handleError = (error, url) => {
    errorMessage.innerHTML = `
      There was an issue adding "${url}": ${error.message}
    `.trim();
    setTimeout(() => errorMessage.innerText = null, 5000);
}

const validateResponse = (response) => {
    if (response.ok) { return response; }
    throw new Error(`Status code of ${response.status} ${response.statusText}`);
}


renderLinks();

要点解析:

fetch()

https://www.jianshu.com/p/a6d00de26c2e

electron 的 shell 模块

可以使用shell模块:使用用户默认的浏览器打开链接

const { shell } = require('electron'); //提供与高层级桌面集成有关的函数

...


linksSection.addEventListener('click', (event) => {
    if (event.target.href) {
      event.preventDefault();
      shell.openExternal(event.target.href); //shell模块:使用用户默认的浏览器打开链接
    }
  });

  ...
  

DOMParser

   const parser = new DOMParser(); //Chrominum提供的文本解析器

数组的.map()函数

https://blog.csdn.net/liminwang0311/article/details/86480829

localStorage

localStorage.setItem(url, JSON.stringify({ title: title, url: url });
...
JSON.parse(localStorage.getItem(key))

posted @ 2020-06-09 22:09  easy5  阅读(797)  评论(0编辑  收藏  举报