当前位置: 首页 > news >正文

b站推广入口软件最牛餐饮营销手段

b站推广入口软件,最牛餐饮营销手段,注册有限公司需要什么资料,如何制作app推广初始化 因网络问题建议使用 cnpm 代替 npm npm init vue # 全选 yes npm i # 进入项目目录后使用 npm i electron electron-builder -D npm i commander -D # 额外组件electron 新建 plugins、src/electron 文件夹 添加 src/electron/background.ts 属于主进程 ipcMain.o…

初始化

因网络问题建议使用 cnpm 代替 npm

npm init vue # 全选 yes
npm i # 进入项目目录后使用
npm i electron electron-builder -D
npm i commander -D # 额外组件

electron

新建 plugins、src/electron 文件夹

添加 src/electron/background.ts

属于主进程

ipcMain.on、ipcMain.handle 都用于主进程监听 ipc,ipcMain.on 用于监听 ipcRenderer.send,ipcMain.handle 用于监听 ipcRenderer.invoke 并 return xxx

ipc 单向:
从渲染进程发向主进程:ipcRenderer.send
从主进程发向渲染进程:window.webContents.send

ipc 双向:
从渲染进程发向主进程,主进程还会返回发向渲染进程:ipcRenderer.invoke
从主进程发向渲染进程,渲染进程还会返回发向主进程:没有类似于 ipcRenderer.invoke 的,需要间接实现。主进程使用 window.webContents.send,渲染进程使用 ipcRenderer.send

渲染进程之间的 ipc 通信:
让主进程中转,也就是“渲染进程1”使用 ipcRenderer.send 到主进程的 ipcMain.on,然后主进程在这个 ipcMain.on 里用相应的 window2.webContents.send 发送到“渲染进程2”里。每个 “const windowxxx = new BrowserWindow“ 就是一个新的渲染进程

import { app, BrowserWindow, screen, ipcMain } from 'electron'
import path from 'path'
import { Command } from 'commander'// 当 electron 准备好时触发
app.whenReady().then(() => {// 使用 c 编译出的 hello.nodetry {var addon = require('./addon/hello')console.log(addon.hello());} catch (error) {console.log(error)}// 命令行参数解析const command = new Commandcommand.option('-m, --maximize', 'maximize window').option('-l, --location <>', 'location of load index page', 'index.html').option('-d, --dev', 'openDevTools').option('--no-sandbox', 'other').parse()const options = command.opts()// 创建窗口const window = new BrowserWindow({// 命令行加 -m 则全屏width: options.maximize ? screen.getPrimaryDisplay().workAreaSize.width : 800,height: options.maximize ? screen.getPrimaryDisplay().workAreaSize.height : 600,autoHideMenuBar: true,webPreferences: {preload: path.join(__dirname, 'preload.js') // 加载 预加载脚本,用于向渲染进程提供使用 ipc 通信的方法}})// 命令行加 -l http://xxx:xxx 则加载该 url 的 index.html,可实时刷新页面的更改,用于调试if (options.location.indexOf(':') >= 0)window.loadURL(options.location)elsewindow.loadFile(options.location)// 命令行加 -d 则打开开发者工具if (options.dev)window.webContents.openDevTools()// ipcipcMain.on('rtm', () => {console.log('rtm')window.webContents.send('mtr')})ipcMain.on('rtm_p', (e, p) => {console.log(p)window.webContents.send('mtr_p', `mtr_p ${p}`)})ipcMain.handle('rtmmtr_p', (e, p) => {console.log(p)return `rtmmtr_p ${p}`})
})

添加 src/electron/preload.ts

预加载脚本,用来给渲染进程提供使用 ipc 的方法
rtm 是渲染进程发向主进程;rtmmtr 是从渲染进程发向主进程,主进程还会返回发向渲染进程;mtr 是主进程发向渲染进程

import { contextBridge, ipcRenderer } from 'electron'contextBridge.exposeInMainWorld('electronAPI', {rtm: () => ipcRenderer.send('rtm'),rtm_p: (p: any) => ipcRenderer.send('rtm_p', p),rtmmtr_p: (p: any) => ipcRenderer.invoke('rtmmtr_p', p),mtr: (p: any) => ipcRenderer.on('mtr', p),mtr_p: (p: any) => ipcRenderer.on('mtr_p', p),
})

添加 src/electron/renderer.d.ts

给渲染进程用的 preload.ts 里的方法的类型声明

export interface IElectronAPI {rtm: () => Promise<any>,rtm_p: (p: any) => Promise<any>,rtmmtr_p: (p: any) => Promise<any>,mtr: (p: any) => Promise<any>,mtr_p: (p: any) => Promise<any>,
}declare global {interface Window {electronAPI: IElectronAPI}
}

添加 plugins/vite.electron.dev.ts

自定义 dev 方法,用于启动 vite 后带起 electron

import type { Plugin } from 'vite'
import type { AddressInfo } from 'net'
import { spawn } from 'child_process'
import fs from 'fs'// 导出Vite插件函数
export const viteElectronDev = (): Plugin => {return {name: 'vite-electron-dev',// 在configureServer中实现插件的逻辑configureServer(server) {// 定义初始化Electron的函数const initElectron = () => {// 使用esbuild编译TypeScript代码为JavaScriptrequire('esbuild').buildSync({entryPoints: ['src/electron/background.ts', 'src/electron/preload.ts'],bundle: true,outdir: 'dist',platform: 'node',external: ['electron']})// 复制 .nodetry {fs.mkdirSync('dist/addon')} catch (error) {}fs.copyFileSync('addon/hello/build/Release/hello.node', 'dist/addon/hello.node')}// electron 运行let electron_run = (ip: string) => {initElectron()// 启动Electron进程并添加相应的命令行参数let electronProcess = spawn(require('electron'), ['dist/background.js', '-l', ip, '-d'])// 监听Electron进程的stdout输出electronProcess.stdout?.on('data', (data) => {console.log(`${data}`);});return electronProcess}// 监听Vite的HTTP服务器的listening事件server?.httpServer?.once('listening', () => {// 获取HTTP服务器的监听地址和端口号const address = server?.httpServer?.address() as AddressInfoconst ip = `http://localhost:${address.port}`let electronProcess = electron_run(ip)// 监听主进程代码的更改以自动编译这些 .ts 并重启 electronfs.watch('src/electron', () => {// 杀死当前的Electron进程electronProcess.kill()electronProcess = electron_run(ip)})})}}
}

添加 plugins/vite.electron.build.ts

自定义 build 方法,这里打包了 linux 的 x64、arm64 的包

import type { Plugin } from 'vite'
import * as electronBuilder from 'electron-builder'
import path from 'path'
import fs from 'fs'// 导出Vite插件函数
export const viteElectronBuild = (): Plugin => {return {name: 'vite-electron-build',// closeBundle是Vite的一个插件钩子函数,用于在Vite构建完成后执行一些自定义逻辑。closeBundle() {// 定义初始化Electron的函数const initElectron = () => {// 使用esbuild编译TypeScript代码为JavaScriptrequire('esbuild').buildSync({entryPoints: ['src/electron/background.ts', 'src/electron/preload.ts'],bundle: true,outdir: 'dist',platform: 'node',external: ['electron']})// 复制 .nodefs.mkdirSync('dist/addon')fs.copyFileSync('addon/hello/build/Release/hello.node', 'dist/addon/hello.node')}// 调用初始化Electron函数initElectron()// 修改package.json文件的main字段,不然会打包失败const json = JSON.parse(fs.readFileSync('package.json', 'utf-8'))json.main = 'background.js'fs.writeSync(fs.openSync('dist/package.json', 'w'), JSON.stringify(json, null, 2))// 创建一个空的node_modules目录 不然会打包失败fs.mkdirSync('dist/node_modules')// 使用electron-builder打包Electron应用程序electronBuilder.build({config: {appId: 'com.example.app',productName: 'vite-electron',directories: {app: path.join(process.cwd(), "dist"), // 被打包的散文件目录output: path.join(process.cwd(), "release"), // 生成的包的目录},linux: {"target": [{"target": "AppImage", // 生成的包的类型 .AppImage"arch": ["x64", "arm64"] // 会对每个架构都会生成对应的包。会下载对应架构的 electron,可能会失败,多试}]}}})}}
}

修改 src/App.vue

添加按钮和 ipc
属于渲染进程

window.electronAPI.xxx() 就是预加载脚本(preload.ts)给渲染进程提供的使用 ipc 的方法
window.electronAPI.mtr 和 …mtr_p (mtr:main to renderer)用于监听主进程发过来的消息
由于 window.electronAPI.rtmmtr_p 使用 ipcRenderer.invoke,这是异步方法,如果不在其前面加 await 而直接获取会得到一个用于异步执行的对象(Promise),其内容包含了需要异步执行的东西,await 就是等待该对象运行结束从而获取正确值,而 await 需要其调用者是异步的,所以 increment() 也加上了 async(异步标志)

<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
import { ref } from 'vue'// 响应式状态
const count = ref(0)// 用来修改状态、触发更新的函数
async function increment() {count.value++window.electronAPI.rtm()window.electronAPI.rtm_p(`rtm_p ${count.value}`)const rtmmtr_p = await window.electronAPI.rtmmtr_p(`rtmmtr_p ${count.value}`)console.log(rtmmtr_p)
}window.electronAPI.mtr(() => {console.log('mtr')
})window.electronAPI.mtr_p((e: any, p: any) => {console.log(p)
})
</script><template><button @click="increment">hhh: {{ count }}</button><header><img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" /><div class="wrapper"><HelloWorld msg="You did it!" /><nav><RouterLink to="/">Home</RouterLink><RouterLink to="/about">About</RouterLink></nav></div></header><RouterView />
</template><style scoped>
header {line-height: 1.5;max-height: 100vh;
}.logo {display: block;margin: 0 auto 2rem;
}nav {width: 100%;font-size: 12px;text-align: center;margin-top: 2rem;
}nav a.router-link-exact-active {color: var(--color-text);
}nav a.router-link-exact-active:hover {background-color: transparent;
}nav a {display: inline-block;padding: 0 1rem;border-left: 1px solid var(--color-border);
}nav a:first-of-type {border: 0;
}@media (min-width: 1024px) {header {display: flex;place-items: center;padding-right: calc(var(--section-gap) / 2);}.logo {margin: 0 2rem 0 0;}header .wrapper {display: flex;place-items: flex-start;flex-wrap: wrap;}nav {text-align: left;margin-left: -1rem;font-size: 1rem;padding: 1rem 0;margin-top: 1rem;}
}
</style>

修改 tsconfig.node.json

添加 “plugins/**/*.ts”

{"extends": "@tsconfig/node18/tsconfig.json","include": ["vite.config.*","vitest.config.*","cypress.config.*","nightwatch.conf.*","playwright.config.*","plugins/**/*.ts"],"compilerOptions": {"composite": true,"module": "ESNext","types": ["node"]}
}

修改 vite.config.ts

添加 plugins

import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'// plugins
import { viteElectronDev } from './plugins/vite.electron.dev'
import { viteElectronBuild } from './plugins/vite.electron.build'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),vueJsx(),viteElectronDev(),viteElectronBuild()],base: './', //默认绝对路径改为相对路径 否则打包白屏resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
})

addon-napi

为了让 electron 调用 c
再新建 addon/hello 目录

添加 addon/hello/hello.c

#include <assert.h>
#include <node_api.h>static napi_value Method(napi_env env, napi_callback_info info) {napi_status status;napi_value world;status = napi_create_string_utf8(env, "hello world", 11, &world);assert(status == napi_ok);return world;
}#define DECLARE_NAPI_METHOD(name, func)                                        \{ name, 0, func, 0, 0, 0, napi_default, 0 }static napi_value Init(napi_env env, napi_value exports) {napi_status status;napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);status = napi_define_properties(env, exports, 1, &desc);assert(status == napi_ok);return exports;
}NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

添加 addon/hello/hello.js

var addon = require('./build/Release/hello')console.log(addon.hello())

添加 addon/hello/binding.gyp

{"targets": [{"target_name": "hello","sources": [ "hello.c" ]}]
}

添加 addon/hello/package.json

{"name": "hello_world","version": "0.0.0","description": "Node.js Addons Example #1","main": "hello.js","private": true,"scripts": {"test": "node hello.js"},"gypfile": true
}

.node 的编译与测试

cd 到 addon/hello

npm i # 安装依赖和编译
node ./ # 测试,会输出 hello world

修改 hello.c 后使用npm i重新编译

使用

启动:npm run dev
打包:npm run build

npm run dev后会在桌面出现应用界面,并自动打开开发者工具,命令行会输出 hello world
修改 src/electron 下的任何文件都会自动编译这些 .ts 并重启 electron

npm run build 后会在 release 下生成 vite-electron-0.0.0.AppImage 和 vite-electron-0.0.0-arm64.AppImage

其他

  • https://xiaoman.blog.csdn.net/article/details/131713875?spm=1001.2014.3001.5502
  • https://www.electronjs.org/zh/docs/latest/tutorial/context-isolation
  • https://www.electronjs.org/zh/docs/latest/tutorial/ipc

文章转载自:
http://tex.pqbz.cn
http://vermination.pqbz.cn
http://pseudopodium.pqbz.cn
http://pukras.pqbz.cn
http://arabella.pqbz.cn
http://unfirm.pqbz.cn
http://whit.pqbz.cn
http://pullout.pqbz.cn
http://bedtiime.pqbz.cn
http://amphitropous.pqbz.cn
http://rhizoid.pqbz.cn
http://hulahula.pqbz.cn
http://obediently.pqbz.cn
http://suprathreshold.pqbz.cn
http://rajahmundry.pqbz.cn
http://valuator.pqbz.cn
http://dilater.pqbz.cn
http://reminiscently.pqbz.cn
http://preen.pqbz.cn
http://sonderclass.pqbz.cn
http://subtopia.pqbz.cn
http://afs.pqbz.cn
http://footpath.pqbz.cn
http://courageously.pqbz.cn
http://roorback.pqbz.cn
http://vision.pqbz.cn
http://hydromancy.pqbz.cn
http://salvador.pqbz.cn
http://uvulitis.pqbz.cn
http://soluble.pqbz.cn
http://fattener.pqbz.cn
http://sporting.pqbz.cn
http://materiality.pqbz.cn
http://impaint.pqbz.cn
http://melodramatise.pqbz.cn
http://spifflicate.pqbz.cn
http://whirlwind.pqbz.cn
http://vmtp.pqbz.cn
http://spacearium.pqbz.cn
http://calumnious.pqbz.cn
http://geranium.pqbz.cn
http://superannuable.pqbz.cn
http://streetwalking.pqbz.cn
http://wehrmacht.pqbz.cn
http://nostoc.pqbz.cn
http://daniel.pqbz.cn
http://angled.pqbz.cn
http://atechnic.pqbz.cn
http://bursitis.pqbz.cn
http://rectum.pqbz.cn
http://alliance.pqbz.cn
http://iridocapsulitis.pqbz.cn
http://asphyxiator.pqbz.cn
http://silverly.pqbz.cn
http://crapshoot.pqbz.cn
http://curule.pqbz.cn
http://giocoso.pqbz.cn
http://scenography.pqbz.cn
http://demote.pqbz.cn
http://happen.pqbz.cn
http://mir.pqbz.cn
http://zingaro.pqbz.cn
http://fecund.pqbz.cn
http://constant.pqbz.cn
http://nebular.pqbz.cn
http://plug.pqbz.cn
http://homeopathic.pqbz.cn
http://cablecast.pqbz.cn
http://haematogenous.pqbz.cn
http://sanctification.pqbz.cn
http://ganof.pqbz.cn
http://tamarind.pqbz.cn
http://knickers.pqbz.cn
http://spermatocide.pqbz.cn
http://totalize.pqbz.cn
http://mandrake.pqbz.cn
http://haggai.pqbz.cn
http://diazo.pqbz.cn
http://nomad.pqbz.cn
http://tops.pqbz.cn
http://microchip.pqbz.cn
http://conferee.pqbz.cn
http://escheatorship.pqbz.cn
http://hazelnut.pqbz.cn
http://metrological.pqbz.cn
http://bathhouse.pqbz.cn
http://densometer.pqbz.cn
http://agglomerative.pqbz.cn
http://kinetoplast.pqbz.cn
http://garotte.pqbz.cn
http://shillelah.pqbz.cn
http://headframe.pqbz.cn
http://piccanin.pqbz.cn
http://phonics.pqbz.cn
http://beachhead.pqbz.cn
http://clothespress.pqbz.cn
http://refragable.pqbz.cn
http://metachrosis.pqbz.cn
http://airscrew.pqbz.cn
http://flamen.pqbz.cn
http://www.dt0577.cn/news/63674.html

相关文章:

  • wordpress 页面与文章seo优化公司信
  • 手机做图片的网站网络营销有什么特点
  • 为啥做网站百度网盘账号登录入口
  • 企业退休做认证进哪个网站泸州网站优化推广
  • 做富集的网站青岛seo用户体验
  • yy刷单做的那些网站长沙官网seo技术厂家
  • 前程无忧网站开发待遇怎么样怎么提交网址让百度收录
  • wordpress云盘当阳seo外包
  • 政府网站建设内容介绍深圳网络推广哪家好
  • 梅州做网站多少钱长沙线上引流公司
  • 晋江住房和城乡建设局网站平台广告推广
  • 建站网站都用不了的世界最新新闻
  • 烟台市建设局网站怎样做百度推广网页
  • 怎么做内网网站网站产品怎么优化
  • 动漫制作专业个人简历重庆seo优化推广
  • 陕西手机网站建设公司排名西安百度框架户
  • 网站专题页面设计欣赏黑马it培训班出来现状
  • zblog可以做视频网站吗seoyoon
  • 详情页设计要遵循基本的思路站长工具查询seo
  • 武隆网站建设联系电话看广告得收益的app
  • 公司网站建设哪家比较好游戏推广怎么做
  • 个人网站申请备案近期时政热点新闻20条
  • 怎么样建网站百度关键词关键词大全
  • 有经验的永州网站建设百度app登录
  • 网站只做内容 不做外链新媒体运营培训
  • 佛山骏域网站建设网站建设流程步骤
  • 旅游网站模板html网站如何做关键词优化
  • ps 制作网站网络营销主要是什么
  • 平面设计套用模板网站拼多多seo怎么优化
  • 如何不用代码做网站百度seo培训公司