指令
v-text
- 作用:设置标签的内容
- 默认写法会替换全部内容,使用差值表达式
{``{ }}
可替换指定内容 - 内部支持写表达式
javascript
<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
指令无论是什么,都会被解析为文本
javascript
<template>
<div>
<p v-html="content"></p>
</div>
</template>
<script setup>
let content="info and message"
</script>
v-on
- 为元素绑定事件
- 事件名不需要写
on
- 指令可以简写为
@
javascript
<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
javascript
<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,实现隐藏
- 指令后面的内容,都会被解析为布尔值
javascript
<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
javascript
<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,只保留:属性名
javascript
<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 数据
javascript
<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指令
- 便捷的设置和获取表单元素的值
- 设定的数据会和表单元素的值相关联
- 绑定的数据 --------- 表单元素的值
javascript
<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
钩子,且销毁前和销毁后的钩子命名更改为beforeUnmount
和unmounted
Index.vue
javascript
<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
javascript
<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
javascript
<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
javascript
<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
javascript
<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函数
通过监听某个值的变化计算出一个新值
javascript
<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
组件
javascript
<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>
使用组件
javascript
<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
组件
javascript
<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>
使用组件
javascript
<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组件
- 在package.json中引入包
javascript
"dependencies": {
"element-plus": "2.4.1",
"vue": "^3.2.33",
"vue-router": "^4.0.14"
},
- 在
main.js
文件中引入Element Plus
,并进行全局注册
javascript
// 引入 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')
- 组件使用
Electron进程间通信模块
Electron 主进程,和渲染进程的通信主要用到两个模块:
ipcMain
和ipcRenderer
以下为electron-egg框架的用法:ipc等同于ipcRenderer
渲染器进程到主进程(双向)------ ipcRenderer.invoke(channel, param) - 渲染进程发送异步消息(invoke/handle 模型)
如果你想从主进程中收到单个响应,比如一个方法调用的结果, 请考虑使用 ipcRenderer.invoke
- 定义通信频道
在/frontend/src/api/main.js中定义
javascript
//os
getPlatformInfo: 'controller.os.getPlatformInfo',
- 主进程添加执行函数
单独在controller目录添加文件os.js
javascript
'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;
- 渲染进程添加异步调用函数
javascript
<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()
- 定义信道
javascript
getScreenSize: 'controller.os.getScreenSize',
- 添加主进程函数
javascript
'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;
- 添加渲染进程调用函数
javascript
<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
- 渲染进程发送异步消息
javascript
<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>
- 主进程在函数中监听
javascript
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
- 主进程
webContents.send
发送消息
javascript
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;
- 渲染进程
ipcRenderer.on
监听消息
javascript
<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>