Electron-Vue基础初探

指令

v-text

  • 作用:设置标签的内容
  • 默认写法会替换全部内容,使用差值表达式{{ }}可替换指定内容
  • 内部支持写表达式
<template>
  <div>
    <h2 v-text="message"></h2>
    <h2> {{ info }}</h2>
  </div>
</template>

<script setup>
let message = "Nodejs"
let info = "Vue"
</script>

v-html

  • 设置元素的innerHtml
  • 内容有html结构会被解析为标签
  • v-text指令无论是什么,都会被解析为文本
<template>
  <div>
    <p v-html="content"></p>
  </div>
</template>

<script setup>
let content="info and message"
</script>

v-on

  • 为元素绑定事件
  • 事件名不需要写on
  • 指令可以简写为@
<template>
  <div>
    <el-button v-on:click="doIt">v-on指令</el-button>
    <el-button @click="doIt">v-on简写</el-button>
    <el-button @dblclick="doDbIt">double click</el-button>
  </div>
</template>

<script setup>
function doIt()
{
  alert("click it")
}

function doDbIt()
{
  alert("double click it")
}
</script>

补充:

  • 事件绑定的方法写成函数调用的形式,可传入自定义参数
  • 定义方法需要定义形参来接受传入的实参
  • 事件后面跟上.修饰符可以对事件进行限制
  • .enter触发的事件为回车
  • 触发事件有多种

demo1

<template>
  <div>
    <el-button @click="sub"> - </el-button>
    <span>{{ num }}</span>
    <el-button @click="add"> + </el-button>
  </div>
</template>

<script setup>
import {ref} from 'vue'
let num = ref(1);

function sub()
{
  num.value -= 1;
}

function add()
{
  num.value += 1;
}
</script>

v-show指令

  • 根据真假切换元素的显示状态
  • 修改元素的display,实现隐藏
  • 指令后面的内容,都会被解析为布尔值
<template>
  <div>
    <el-button @click="changeIsShow"> 切换显示状态 </el-button>
    <el-button v-show="isShow"> back </el-button>
  </div>
</template>

<script setup>
import {ref} from 'vue'
let isShow = ref(true);
function changeIsShow()
{
  isShow.value = !isShow.value;
}
</script>

v-if指令

  • 根据真假切换元素的显示状态
  • 操纵dom元素切换显示状态
  • 表达式为true,元素存在于dom树中;为false,从dom树中移除
  • 频繁切换用v-show;反之用v-if
<template>
  <div>
    <el-button @click="changeIsShow"> 切换显示状态 </el-button>
    <el-button v-show="isShow"> v-show指令 </el-button>
    <el-button v-if="isShow"> v-if指令 </el-button>
  </div>
</template>

<script setup>
import {ref} from 'vue'
let isShow = ref(true);
function changeIsShow()
{
  isShow.value = !isShow.value;
}
</script>

v-bind

  • 为元素绑定属性
  • 完整写法:v-bind:属性名
  • 简写:省略v-bind,只保留:属性名
<template>
  <div>
    <img :src="imgSrc">
    <br>
    <img v-bind:src="imgSrc">
  </div>
</template>

<script setup>
import {ref} from 'vue'
let imgSrc="http://itheima.com/images/logo.png"
</script>

v-for指令

  • 根据数据生成列表结构
  • 通常与数组结合使用
  • 语法是(item, index) in 数据
<template>
  <div>
    <el-col v-for="it in arr">
      姓名:{{ it.name }}, 年龄:{{ it.age }}
    </el-col>
    <br>
    <el-button @click="add">添加人物</el-button>
    <el-button @click="deleteOne">删除所有人物</el-button>
  </div>
</template>

<script setup>
import {ref, reactive} from 'vue'

let arr = reactive([
  {name: '韩立', age: '199', feature: 'run'},
  {name: '玄骨', age: '1000', feature: 'play'},
  {name: '元瑶', age: '19', feature: 'eee'}
])

function add()
{
  arr.push({name:'叶凡', age: '24'});
}

function deleteOne()
{
  arr.shift();
}
</script>

v-model指令

  • 便捷的设置和获取表单元素的值
  • 设定的数据会和表单元素的值相关联
  • 绑定的数据 ——— 表单元素的值
<template>
  <div>
    <el-select v-model="name" placeholder="请选择">
      <el-option v-for="item in arr"
      :key="item.name"
      :label="item.name"
      :value="item.name">
      </el-option>
    </el-select>
  </div>
</template>

<script setup>
import {ref, reactive} from 'vue'

let arr = reactive([
  {name: '韩立', age: '199', feature: 'run'},
  {name: '玄骨', age: '1000', feature: 'play'},
  {name: '元瑶', age: '19', feature: 'eee'}
])
</script>

class与style绑定

vue3的生命周期

相比vue2,增加了 setup 钩子,且销毁前和销毁后的钩子命名更改为 beforeUnmountunmounted

Index.vue

<script setup>
import Demo from './Demo.vue'
import Demo2 from './Demo2.vue'
import { ref } from 'vue'
const isComDestory = ref(true)
const isOptionDestory = ref(true)
</script>
 
<template>
  <div>
    <h1>
      v3
      <button @click="isComDestory = false">引入组合式子组件</button>
      <button @click="isComDestory = true">销毁组合式子组件</button>
      <button @click="isOptionDestory = false">引入选项式子组件</button>
      <button @click="isOptionDestory = true">销毁选项式子组件</button>
    </h1>
    <Demo v-if="!isComDestory"></Demo>
    <Demo2 v-if="!isOptionDestory"></Demo2>
  </div>
</template>
 
<style scoped>
button {
  padding: 20px;
  font-size: 16px;
}
</style>

Demo.vue

<script setup>
import {
    onMounted,
    onBeforeMount,
    onBeforeUpdate,
    onUpdated,
    onBeforeUnmount,
    onUnmounted,
    ref,
} from 'vue'

const sum = ref(1)
console.log('子组件1 setup')
onBeforeMount(() => {
    console.log('子组件1 onBeforeMount')
})
onMounted(() => {
    console.log('子组件1 onMounted')
})
onBeforeUpdate(() => {
    console.log('子组件1 onBeforeUpdate')
})
onUpdated(() => {
    console.log('子组件1 onUpdated')
})
onBeforeUnmount(() => {
    console.log('子组件1 onBeforeUnmount')
})
onUnmounted(() => {
    console.log('子组件1 onUnmounted')
})
</script>

<template>
    <div>
        <h2>我是子组件1</h2>
        <h2> {{ sum }} <button @click="sum++">+1</button></h2>
    </div>
</template>

Demo2.vue

<script>
import { ref } from 'vue'

export default {
  setup() {
    const sum = ref(1)
    console.log('子组件2 setup')
    return { sum }
  },
  beforeCreate() {
    console.log('子组件2 beforeCreate')
  },
  created() {
    console.log('子组件2 created')
  },
  beforeMount() {
    console.log('子组件2 beforeMount')
  },
  mounted() {
    console.log('子组件2 mounted')
  },
  beforeUpdate() {
    console.log('子组件2 beforeUpdate')
  },
  updated() {
    console.log('子组件2 updated')
  },
  beforeUnmount() {
    console.log('子组件2 beforeUnmount')
  },
  unmounted() {
    console.log('子组件2 unmounted')
  },
}
</script>

<template>
    <div>
        <h2>我是子组件2</h2>
        <h2> {{ sum }} <button @click="sum++">+1</button></h2>
    </div>
</template>

响应式数据

ref

<template>
  <div>
    <h1>v3</h1>
    <h3>{{ sum }}</h3>
    <button @click="add">+1</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const sum = ref(1)
function add() {
  sum.value++
}
</script>
 
<style scoped></style>

reactive

<template>
  <div>
    <h1>v3</h1>
    <h1>{{ sum }}</h1>
    <h3>姓名:{{ person.name }}</h3>
    <h3>年龄:{{ person.age }}</h3>
    <h3>工作:{{ person.job.j1.jname }}</h3>
    <h3 v-if="person.hobby">爱好: {{ person.hobby }}</h3>
    <button @click="person.name += '-'">修改姓名</button>
    <button @click="person.age++">修改年龄</button>
    <button @click="person.job.j1.jname += '!'">修改工作</button>
    <button @click="add">增加爱好</button>
    <button @click="deleteHB">删除爱好</button>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const person = reactive({
  name: '韩立',
  age: 12,
  job: {
    j1: {
      jname: '跑路',
    },
  },
})
 
function add() {
  person.hobby = ['唱', '跳', 'rap']
}
function deleteHB() {
  delete person.hobby
}
</script>
 
<style scoped></style>

计算属性和监听

computed函数

通过监听某个值的变化计算出一个新值

 <template>
  <div>
    <h1>v3</h1>
    <h2>
      ref 定义的 count: {{ count }} <button @click="count++">count++</button>
    </h2>
    <h2>计算属性 num1: {{ num1 }} <button @click="num1++">num1++</button></h2>
    <h2>计算属性 num2: {{ num2 }} <button @click="num2++">num2++</button></h2>
  </div>
</template>
<script setup>
import { ref, computed } from 'vue'
const count = ref(1)
const num1 = computed(() => count.value + 1)
const num2 = computed({
  get() {
    return count.value + 1
  },
  set(val) {
    count.value = val + 1
  },
})
</script>

watch函数

watchEffect函数

自定义单文件vue组件

Props 声明

defineProps 是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入。声明的 props 会自动暴露给模板。defineProps 会返回一个对象,其中包含了可以传递给组件的所有 props

BlogPost组件

<template>
    <p>{{ title }}</p>
</template>


<script setup>
import { ref, onMounted } from 'vue';

const count = ref(0);

const props = defineProps(['title']);

onMounted(() => {
    console.log(props.title)
});
</script>

使用组件

<script setup>
import BlogPost from './BlogPost.vue';
import { ref } from 'vue';

const posts = ref([
  { id: 1, title: 'han li' },
  { id: 2, title: 'zi ling' },
  { id: 3, title: 'yao xi' }
]);
</script>

<template>
  <h1>Here is a child component!</h1>
  <BlogPost title="My journey with Vue"/>
  <BlogPost title="Why Vue is so fun"/>
  <BlogPost
    v-for="post in posts"
    :key="post.id"
    :title="post.title"
  />
</template>

自定义事件defineEmits

BlogPost组件

<template>
    <p>{{ title }}</p>
    <el-button @click="enlarge">enlarge-text</el-button>
</template>

<script setup>
const props = defineProps(['title']);
const emit = defineEmits(['enlarge-text']);

const enlarge = () => {
    console.log('[BlogPost]: enlarge');
    emit('enlarge-text');
}

</script>

使用组件

<script setup>
import BlogPost from './BlogPost.vue';
import { ref } from 'vue';

const postFontSize = ref(1);
const enlarge = () => {
  console.log('[Index]: enlarge');
  postFontSize.value += 0.1;
}
</script>

<template>
  <div :style="{ fontSize: postFontSize + 'em' }">
    <h1>Here is a child component!</h1>
    <BlogPost title="My journey with Vue" @enlarge-text="enlarge"/>
  </div>
</template>

引入Element-Plus组件

  1. 在package.json中引入包
  "dependencies": {
    "element-plus": "2.4.1",
    "vue": "^3.2.33",
    "vue-router": "^4.0.14"
  },
  1. main.js 文件中引入 Element Plus,并进行全局注册
// 引入 Element Plus 和样式文件
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';

const app = createApp(App)
app.config.productionTip = false

// components
for (const i in components) {
  app.component(i, components[i])
}

app.use(ElementPlus).use(Router).mount('#app')
  1. 组件使用

Electron进程间通信模块

Electron 主进程,和渲染进程的通信主要用到两个模块:ipcMainipcRenderer

以下为electron-egg框架的用法:ipc等同于ipcRenderer

渲染器进程到主进程(双向)—— ipcRenderer.invoke(channel, param) - 渲染进程发送异步消息(invoke/handle 模型)

如果你想从主进程中收到单个响应,比如一个方法调用的结果, 请考虑使用 ipcRenderer.invoke

  1. 定义通信频道

在/frontend/src/api/main.js中定义

 //os
 getPlatformInfo: 'controller.os.getPlatformInfo',
  1. 主进程添加执行函数

单独在controller目录添加文件os.js

'use strict'

const { Controller } = require('ee-core');
const Log = require('ee-core/log');
const os = require('os');
const platformInfo = os.platform();

class OsController extends Controller {

  constructor(ctx) {
    super(ctx);
  }

  /**
   * 所有方法接收两个参数
   * @param args 前端传的参数
   * @param event - ipc通信时才有值。详情见:控制器文档
   */

  getPlatformInfo () {

    return platformInfo;
  }
}

OsController.toString = () => '[class OsController]';
module.exports = OsController;
  1. 渲染进程添加异步调用函数
<template>
  <div>
    <el-button @click="getPlatformInfo">获取本地平台信息</el-button>
    <h>
      {{ platformInfo }}
    </h>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { ipc } from "@/utils/ipcRenderer";
import { ipcApiRoute } from "@/api/main";

const platformInfo = ref('');
async function getPlatformInfo()
{
  try {
    const result = await ipc.invoke(ipcApiRoute.getPlatformInfo);
    platformInfo.value = result;
    console.error('获取平台信息成功:', platformInfo.value);
  } catch (error) {
    console.error('获取平台信息失败:', error);
  }
}
</script>

渲染器进程到主进程(双向)—— ipcRenderer.sendSync(channel, param) - 渲染进程发送同步消息(send/on 模型)

发送同步消息将阻止整个渲染过程直到收到回复。 这样使用此方法只能作为最后手段。 使用异步版本更好 invoke()

  1. 定义信道
getScreenSize: 'controller.os.getScreenSize',
  1. 添加主进程函数
'use strict'

const { screen } = require("electron");
const { Controller } = require('ee-core');
const Log = require('ee-core/log');
const os = require('os');

const platformInfo = os.platform();

class OsController extends Controller {

  constructor(ctx) {
    super(ctx);
  }
  
  getPlatformInfo () {

    return platformInfo;
  }

  getScreenSize() {
    const primaryDisplay = screen.getPrimaryDisplay();
    return primaryDisplay.workAreaSize;
  }
}

OsController.toString = () => '[class OsController]';
module.exports = OsController;
  1. 添加渲染进程调用函数
<template>
  <div>
    <el-button>本地窗口大小:</el-button>
    <h>
      {{ width }} {{ height }}
    </h>
  </div>
</template>

<script setup>
import { ipc } from "@/utils/ipcRenderer";
import { ipcApiRoute } from "@/api/main";

// 获取窗口宽度
const {width, height} =  ipc.sendSync(ipcApiRoute.getScreenSize);

</script>

渲染器进程到主进程(单向)—— 渲染进程ipcRenderer.send发送异步消息,主进程ipcMain.on监听

如果你不需要回复此消息,请考虑使用 ipcRenderer.send

  1. 渲染进程发送异步消息
<template>
  <div>
    <el-button @click="closeApp">退出</el-button>
  </div>
</template>

<script setup>
const { ipcRenderer } = require('electron');

function closeApp()
{
  console.log("[ipcrenderer] exit");
  ipcRenderer.send('close');
}

</script>
  1. 主进程在函数中监听
const { Application } = require('ee-core');
const { ipcMain, app } = require('electron');
class Index extends Application {

  constructor() {
    super();
    // this === eeApp;
  }

  /**
   * core app have been loaded
   */
  async ready () {
    // do some things

    ipcMain.on('close', async() => {
      console.log("[ipcMain] close app");
      app.exit();
    })
  }

  /**
   * electron app ready
   */
  async electronAppReady () {
    // do some things
  }

  /**
   * main window have been loaded
   */
  async windowReady () {
    // do some things
    // 延迟加载,无白屏
    const winOpt = this.config.windowsOption;
    if (winOpt.show == false) {
      const win = this.electron.mainWindow;
      win.once('ready-to-show', () => {
        win.show();
        win.focus();
      })
    }
  }

  /**
   * before app close
   */  
  async beforeClose () {
    // do some things

  }
}

Index.toString = () => '[class Index]';
module.exports = Index;

主进程到渲染器进程(双向)—— ipcRenderer.on(channel, listener) - 监听 channel, 当新消息到达,调用 listener

  1. 主进程webContents.send发送消息
const { Application } = require('ee-core');
const { ipcMain} = require('electron');
const CoreWindow = require('ee-core/electron/window');
class Index extends Application {

  constructor() {
    super();
    // this === eeApp;
  }

  /**
   * core app have been loaded
   */
  async ready () {
    // do some things
  }

  /**
   * electron app ready
   */
  async electronAppReady () {
    // do some things

    ipcMain.on('ipcMsg', () => {
      console.log("ready to send load-success");
      const mainWin = CoreWindow.getMainWindow();
  
      mainWin.webContents.send("load-success");
    })

  }

  /**
   * main window have been loaded
   */
  async windowReady () {
    // do some things
    // 延迟加载,无白屏
    const winOpt = this.config.windowsOption;
    if (winOpt.show == false) {
      const win = this.electron.mainWindow;
      win.once('ready-to-show', () => {
        win.show();
        win.focus();
      })
    }
  }

  /**
   * before app close
   */  
  async beforeClose () {
    // do some things

  }
}

Index.toString = () => '[class Index]';
module.exports = Index;
  1. 渲染进程ipcRenderer.on监听消息
<template>
  <div>
    <el-button @click="ipcSendMsg">主进程发送,渲染进程接收</el-button>
  </div>
</template>

<script setup>
import { onMounted } from 'vue';
import { ipc } from '@/utils/ipcRenderer';
const { ipcRenderer } = require('electron');

function ipcSendMsg()
{
  ipc.send('ipcMsg');
}

onMounted(() => {
  ipc.on('load-success', () => {
    console.log('load success');
  })
})

</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值