Прикосновение рук к практическому руководству по Electron + Vue (2)

Electron
Прикосновение рук к практическому руководству по Electron + Vue (2)

Серия статей:

1 электронное обновление

19 мая 2020 года Electron обновил последнюю версию 9.0.0, которая принесла много улучшений, здесь я не буду повторять подробности, вы можете взглянуть на официальное введение:GitHub.com/электрон/плохой…

Что ж, теперь мы обновим проект, инициализированный в предыдущем уроке, доElectron9.0.0, пока два простых шага:
1. Переустановите прямо из командной строкиyarn add electronВы можете перейти на последнюю версию Electron;
2. Удалите каталог srcbackground.jsкод в файлеapp.allowRendererProcessReuse = true, эта строка кода на самом деле то, что мы добавили в прошлом уроке Версия 9.0 была установлена ​​как значение по умолчанию, поэтому здесь она нам не нужна.

2 Введение в проект

Подсчитано, что все не могут не видеть этого: ты так долго был BB, над каким подпроектом ты собираешься работать...
Кхм, мой горшок - это мой горшок, я должен ввести первый в начале и перетащить его в настоящее... Этот практический урок на самом деле не сложный проект, это подделка有道云笔记, верно, это имитация того-то и того-то. . Конечно, ввиду проблемы со временем, я не должен копировать все это, а только выбрать часть записи файла Markdown. Здесь у меня есть небольшое предложение:"Не ради подражания, а для того, чтобы совместить знания и навыки, полученные в проекте, и сделать выводы из чего-то одного, это наша конечная цель."

3 Если работник хочет хорошо работать, он должен сначала заточить свои инструменты

Прежде чем приступить к формальному написанию кода, необходимо иметь один из лучших фронтенд-редакторов.Visual Studio Code, Конечно, это вопрос доброжелательных людей, видящих благожелательность, и мудрых людей, видящих мудрость, самое подходящее для вас - самое лучшее! Если вы решите не использовать этот редактор, вы можете просто пропустить этот раздел. Требуемый плагинESLintа такжеPrettier - Code formatter, я рекомендую свой общий стиль кода и настройки eslint, а также создаю три новых файла в корневом каталоге проекта..editorconfig,.eslintrc.js,.prettierrc.js,Как показано ниже: "Ниже показано отображение кода. Здесь показаны только стили eslint и стиля кода, используемые в текущем проекте. Вы можете выбрать, использовать их или нет."

# 这是 .editorconfig 文件内容

[*.{js,jsx,ts,tsx,vue}] indent_style = space indent_size = 2 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true max_line_length = 120

// 这是 .eslintrc.js 文件内容
module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: ['plugin:vue/essential', '@vue/airbnb'],
  parserOptions: {
    parser: 'babel-eslint'
  },
  rules: {
    'no-console': 0,
    'no-debugger': 0,
    semi: ['error', 'never'], // 禁用 分号
    'no-multiple-empty-lines': ['error'], // 代码空行 数量
    'linebreak-style': [0, 'error', 'windows'], // 使用windows的换行
    'comma-dangle': [2, 'never'], //  对象数组最后一个不带逗号
    'no-trailing-spaces': 0, // 禁用 校验代码末尾带空格
    'import/no-dynamic-require': 0, // 禁用 动态require
    'import/no-unresolved': 0,
    'no-param-reassign': 0, // 声明为函数参数的变量可能会引起误解
    'max-len': ['error', 120], // 单行代码最大长度
    'guard-for-in': 0, // 禁用 禁用for in 循环
    'no-shadow': 0, // 禁用  禁止页面内相容参数名
    'object-shorthand': 0, // 禁用 禁止对象内使用带引号字符串
    'no-restricted-syntax': 0,
    'no-plusplus': 0, // 禁用 ++
    'consistent-return': 0, // 关闭箭头函数必须要return
    'no-return-assign': 0, // return 语句中不能有赋值表达式
    'global-require': 0, // 关闭禁止使用requrie
    'prefer-promise-reject-errors': 0, // 这条规则旨在确保承诺只被Error对象拒绝。
    'import/extensions': 'off', // 禁用文件名详细文件类型后缀
    'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
    'arrow-parens': ['error', 'as-needed'], // 箭头函数参数括号,可选 always:(默认)在所有情况下都需要参数;as-needed:当只有一个参数时允许省略参数
    'no-undef': 0, // 关闭显式声明全局变量的要求
    'class-methods-use-this': 0,
    'no-underscore-dangle': ['error', { allow: ['_id'] }], // 允许指定的标识符具有悬挂下划线
    camelcase: 0, // 关闭使用骆驼拼写法
    'no-global-assign': 0, // 允许修改只读全局变量,
    'space-before-function-paren': [
      'error',
      {
        anonymous: 'never',
        named: 'never',
        asyncArrow: 'always'
      }
    ],
    // 对象解构不需要换行
    'object-curly-newline': [
      'error',
      {
        ObjectPattern: {
          multiline: true
        }
      }
    ],
    'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }] // 允许在表达式中使用三元运算符,类似于短路评估
  }
}

// 这是 .prettierrc.js 文件内容
module.exports = {
  semi: false, // 去掉分号
  singleQuote: true, // 使用单引号
  printWidth: 120, // 单行代码最大长度
  trailingComma: 'none' // 去掉结尾逗号(对象,数组等)
}

Возьми! Теперь мы можем с удовольствием программировать...

4 Развитие левой панели

有道云笔记截图
Скриншот облачной заметки Youdao

Как видите, левая панель - это список файлов.Нам нужно не только сделать здесь список на картинке, но и добавить поисковую строку вверху списка, чтобы мы могли легко и быстро искать по списку Примечания. В настоящее время также необходимы функции добавления заметок и импорта заметок.Посмотрим на готовый продукт в этом разделе:左侧面板成品图

4.1 Общий вид

Давайте сначала удалим лишние страницы и компоненты в проекте:
vue-electron-notes/src/components/HelloWorld.vue
vue-electron-notes/src/views/About.vue
Уменьшенный файл маршрутизации:

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/views/Home')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

сокращенныйApp.vueдокумент:

<template>
  <div id="app">
    <router-view />
  </div>
</template>

<style lang="less">
* {
  margin: 0;
  padding: 0;
  outline: none;
  box-sizing: border-box;
}
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}
</style>

Подстановочный знак css * ради удобства и скорости используется просто и грубо, но в реальных проектах этого делать не рекомендуется, и вы сами поймете...

Мы продолжаем модифицировать каталог просмотраHome.vueфайла, используйте раскладку flex, чтобы установить самую распространенную двухколоночную раскладку (о крутости flex я много говорить не буду, не говоря уже о том, что здесь не нужно учитывать css-совместимость), левая панель имеет фиксированную ширина, а правая область редактирования контента является адаптивной:

<template>
  <div class="app-wrapper">
    <div class="sidebar-container"></div>
    <div class="main-container"></div>
  </div>
</template>

<script>
export default {
  name: 'Home'
}
</script>

<style lang="less" scoped>
.app-wrapper {
  display: flex;
  .sidebar-container {
    width: 300px;
    height: 100vh;
    border-right: 1px solid #eaeefb;
  }
  .main-container {
    flex: 1;
  }
}
</style>

4.2 Представляем element-ui и библиотеку иконок Fontawesome

Создайте папку в каталоге srcplugin, здесь размещаются все внешние фреймворки и плагины, которые мы будем внедрять в будущем. мы используем командную строкуyarn add element-uiУстановите element-ui, затем создайте новый файл в файле плагина.element-ui.js:

/*
 * @Description: 引入 element-ui 框架
 * @Author: sufen
 * @Date: 2020-05-21 09:58:49
 * @LastEditTime: 2020-05-21 09:59:20
 * @LastEditors: sufen
 */
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI, { size: 'small' })

Продолжайте устанавливать библиотеку значков fontawesome, сначала установите все зависимости значков, а затем добавляйте нужные значки по мере необходимости.

MacBook-Pro:vue-electron-notes Bill$ yarn add @fortawesome/vue-fontawesome @fortawesome/free-solid-svg-icons @fortawesome/fontawesome-svg-core @fortawesome/free-brands-svg-icons @fortawesome/free-regular-svg-icons

Затем создайте новый файл в файле плагинаfortawesome.js, faMarkdown и faUserSecret в нем — это значки, которые мы ввели по запросу.Если нам понадобятся новые значки в будущем, мы можем просто добавить их сюда:

/*
 * @Description: fortawesome 图标库
 * @Author: sufen
 * @Date: 2020-05-21 09:55:29
 * @LastEditTime: 2020-05-21 10:06:46
 * @LastEditors: sufen
 */
import Vue from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faUserSecret } from '@fortawesome/free-solid-svg-icons'
import { faMarkdown } from '@fortawesome/free-brands-svg-icons'
// import { faUserSecret } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'

library.add(faUserSecret, faMarkdown)

Vue.component('font-awesome-icon', FontAwesomeIcon)

Вышеупомянутые два еще не закончены, и, наконец, нам нужноmain.jsВнесено в файл:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import '@/plugin/element-ui'
import '@/plugin/fortawesome'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

Пока мы закончилиelement-uiа такжеfortawesomeВнедрение , вы можете с удовольствием использовать его в проекте, если вы мне не верите, попробуйте 😊

4.2 Компонент поиска FileSearch

Добавлен в каталог компонентов компонентовFileSearchКомпонент, этот компонент в основном состоит из поля ввода и раскрывающегося меню, оба из которых мы можем напрямую использовать. Компоненты элементов, следует отметить, что здесь мы используем новые в Vue v2.4.$attrsа также$listenersАтрибуты.

attrs: содержит привязки атрибутов (кроме класса и стиля), которые не считаются (и не должны быть) реквизитами в родительской области. Когда компонент не объявляет никаких реквизитов, все привязки родительской области (кроме класса и стиля) включаются сюда и могут быть переданы внутренним компонентам через v-bind="$attrs" - очень полезно при создании компонентов более высокого уровня.

listeners: содержит прослушиватели событий v-on в родительской области (без декоратора .native). Его можно передать во внутренние компоненты через v-on=”$listeners” — очень полезно при создании компонентов более высокого уровня.

在我们编写 vue 高阶组件中,这两个属性简直就是神器,简直不要太爽! ! !

FileSearchИспользуется непосредственно при вызове компонентаv-modelПривяжите контент, который нужно искать, и создайте и импортируйте файлы через$emitВызов пользовательских событий — это базовые знания Vue, поэтому я не буду здесь говорить больше. Взгляните на то, что мы сделалиFileSearchИсходный код компонента:

<!--
 * @Description: 左侧文件搜索组件
 * @Author: sufen
 * @Date: 2020-05-20 16:08:49
 * @LastEditTime: 2020-05-21 10:36:49
 * @LastEditors: sufen
 -->
<template>
  <div class="search-container">
    <el-input placeholder="请输入内容" v-bind="$attrs" v-on="$listeners">
      <el-button slot="append" icon="el-icon-search" />
    </el-input>
    <el-dropdown>
      <el-button type="primary" icon="el-icon-circle-plus-outline" circle />
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item @click="createFile()">新建笔记</el-dropdown-item>
        <el-dropdown-item divided @click="importFile()">导入文件</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
export default {
  name: 'FileSearch',
  methods: {
    // 新建笔记
    createFile() {
      this.$emit('create')
    },
    // 导入文件
    importFile() {
      this.$emit('import')
    }
  }
}
</script>

<style lang="less" scoped>
.search-container {
  display: flex;
  align-items: center;
  padding: 12px 10px;
  background: #daecfe;

  .el-dropdown {
    .el-button--small {
      margin-left: 10px;
      padding: 6px;
      font-size: 14px;
      border-radius: 30%;
    }
  }
}
</style>

4.3 Компонент списка файлов FileList

Добавлен в каталог компонентов компонентовFileListКомпоненты, мы Этот раздел предназначен для завершения такого списка, как назад, чтобы использовать контекстное меню и так далее, которые мы позже используем, чтобы сказать, как идти шаг за шагом.
Как видите, реквизиты наших компонентов получаютfileListмассив, затем передатьv-forЭто делается после рендеринга напрямую. Каждыйliоба используютflexмакет,liВключая заголовок нашего файла и время последней модификации файла, я должен сказать, что flex на самом деле является артефактом макета, и он использовался все время! Конечно, иконка использует прекрасную библиотеку иконок, которую мы представили ранее.Конкретный код введения иконки перед нами:

import { faMarkdown } from '@fortawesome/free-brands-svg-icons'
library.add(faMarkdown)

Тогда мы непосредственноFileListВ компоненте используется компонент fortawesome, и значок уценки уже отображается.После небольшой модификации стиля для настройки интервала будет идеально:

<font-awesome-icon :icon="['fab', 'markdown']" />

Если это только заканчивается здесь, то этот компонент действительно слишком нетехнический.
По мере того, как у нас будет все больше и больше файлов, длина списка будет становиться все больше и больше, поэтому неизбежно будут полосы прокрутки.Как программист с преследованием, родная полоса прокрутки браузера для меня определенно неприемлема, это просто некрасиво Это не элегантно вообще... Чтобы решить эту проблему, не делая свои собственные колеса, я выбрал скрытый компонент el-scrollbar из element-ui и взглянул на эффект использования официального документа:

Хотя этот компонент не приведен в официальной документации, он есть в исходном коде. Таким образом, мы можем напрямую использовать:

<el-scrollbar></el-scrollbar>

Есть еще некоторые ямки, на которые следует обратить внимание при использовании этого компонента, вы можете обратиться кэта статьяТо, что было написано, уже написано четко и ясно, поэтому повторяться здесь не буду.

Взгляните на наш окончательный полный код компонента:

<!--
 * @Description: 左侧文件列表组件
 * @Author: sufen
 * @Date: 2020-05-20 16:18:34
 * @LastEditTime: 2020-05-21 10:37:18
 * @LastEditors: sufen
 -->
<template>
  <el-scrollbar class="file-list" wrap-class="scrollbar-filelist" :noresize="false" tag="ul">
    <li v-for="(item, index) in fileList" :key="index" class="file-item">
      <font-awesome-icon :icon="['fab', 'markdown']" class="item-icon" />
      <p class="item-title">{{ item.title }}</p>
      <p class="item-time">{{ item.time }}</p>
    </li>
  </el-scrollbar>
</template>

<script>
export default {
  name: 'FileList',
  props: {
    fileList: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {}
  }
}
</script>

<style lang="less" scoped>
.file-list {
  user-select: none;
  .file-item {
    display: flex;
    align-items: center;
    height: 55px;
    border-bottom: 1px solid #eaeefb;

    .item-icon {
      margin-left: 20px;
      margin-right: 12px;
    }

    .item-title {
      flex: 1;
      margin-right: 5px;
      font-size: 14px;
      text-overflow: ellipsis;
      white-space: nowrap;
      overflow: hidden;
    }
    .item-time {
      width: 80px;
      font-size: 12px;
    }
  }
}
</style>
<style lang="less">
.scrollbar-filelist {
  height: calc(100vh - 56px);
  overflow-x: hidden !important;
}
.el-scrollbar__bar {
  opacity: 1;

  &.is-vertical {
    right: 0px;
    width: 5px;
    .el-scrollbar__thumb {
      background-color: rgba(144, 147, 153, 0.5);
    }
  }
}
</style>

4.4 Введение компонента

Два компонента, необходимые для левой панели, были завершены выше. Теперь пришло время представить их на главной странице, чтобы увидеть окончательный эффект. В каталоге просмотраHome.vueНапишите в файле домашней страницы:

<template>
  <div class="app-wrapper">
    <div class="sidebar-container">
      <file-search v-model="searchTitle" />
      <file-list :fileList="fileList" />
    </div>
    <div class="main-container"></div>
  </div>
</template>

<script>
import FileSearch from '@/components/FileSearch'
import FileList from '@/components/FileList'

export default {
  name: 'Home',
  components: { FileSearch, FileList },
  data() {
    return {
      searchTitle: '',
      fileList: [
        { id: 1, title: '文件名 1', time: '2020-06-21' },
        { id: 2, title: '文件名 2', time: '2020-06-21' },
        { id: 3, title: '文件名 3', time: '2020-06-21' },
        { id: 4, title: '文件名 4', time: '2020-06-21' },
        { id: 5, title: '文件名 5', time: '2020-06-21' },
        { id: 6, title: '文件名 6', time: '2020-06-21' },
        { id: 1, title: '文件名 1', time: '2020-06-21' },
        { id: 2, title: '文件名 2', time: '2020-06-21' },
        { id: 3, title: '文件名 3', time: '2020-06-21' },
        { id: 4, title: '文件名 4', time: '2020-06-21' },
        { id: 5, title: '文件名 5', time: '2020-06-21' },
        { id: 6, title: '文件名 6', time: '2020-06-21' }
      ]
    }
  }
}
</script>

<style lang="less" scoped>
.app-wrapper {
  display: flex;
  .sidebar-container {
    width: 300px;
    height: 100vh;
    border-right: 1px solid #eaeefb;
  }
  .main-container {
    flex: 1;
  }
}
</style>

Список последнего дерева файлов:

├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   ├── FileList
│   │   │   └── index.vue
│   │   └── FileSearch
│   │       └── index.vue
│   ├── plugin
│   │   ├── element-ui.js
│   │   └── fortawesome.js
│   ├── router
│   │   └── index.js
│   ├── store
│   │   └── index.js
│   ├── views
│   │   └── Home.vue
│   ├── App.vue
│   ├── background.js
│   └── main.js
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── .prettierrc.js
├── README.md
├── babel.config.js
└── package.json

Возьми!这就是我们左侧面板的最后效果图:左侧面板成品图

Если вы думаете, что эта статья написана также, в этой дряхлой бесстыдно ищет похвалы! 😉