范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Electron结合React和TypeScript进行开发

  结合React+TypeScript进行Electron开发1. electron基本简介
  electron是使用JavaScript,HTML和CSS构建 跨平台 的 桌面应用程序 。我们可以使用一套代码打包成Mac、Windows和Linux的应用,electron比你想象的更简单,如果把你可以建一个网站,你就可以建一个桌面应用程序,我们只需要把精力放在应用的核心上即可。
  为什么选择electron?Electron 可以让你使用纯JavaScript调用丰富的原生APIs来创造桌面应用。你可以把它看作是专注于桌面应用。 在PC端桌面应用开发中,nwjs和electron都是可选的方案,它们都是基于Chromium和Node的结合体,而electron相对而言是更好的选择方案,它的社区相对比较活跃,bug比较少,文档相对利索简洁。 electron相对来说比nw.js靠谱,有一堆成功的案例:Atom编辑器 Visual Studio Code WordPress等等。 Node.js的所有内置模块都在Electron中可用。 2. 快速上手2.1 安装React(template为ts)yarn create react-app electron-demo-ts --template typescript2.2 快速配置React
  工程架构
  index.html                                   electron App              
  App.tsx import React from "react" export default function App() {  return (    App  )}
  index.tsx import React from "react";import ReactDOM from "react-dom/client";import App from "./App";import reportWebVitals from "./reportWebVitals"; const root = ReactDOM.createRoot(  document.getElementById("root") as HTMLElement);root.render(  //       // ); // If you want to start measuring performance in your app, pass a function// to log results (for example: reportWebVitals(console.log))// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitalsreportWebVitals();2.3 安装electron
  将 electron  包安装到您的应用程序的devDependencies  .// npmnpm install --save-dev electron// yarnyarn add --dev electron2.4 配置main.js、preload.js和package.json文件
  main.js // 导入app、BrowserWindow模块// app 控制应用程序的事件生命周期。事件调用app.on("eventName", callback),方法调用app.functionName(arg)// BrowserWindow 创建和控制浏览器窗口。new BrowserWindow([options]) 事件和方法调用同app// Electron参考文档 https://www.electronjs.org/docsconst {app, BrowserWindow, nativeImage } = require("electron")const path = require("path")// const url = require("url");  function createWindow () {    // Create the browser window.    const mainWindow = new BrowserWindow({        width: 800, // 窗口宽度        height: 600,  // 窗口高度        // title: "Electron app", // 窗口标题,如果由loadURL()加载的HTML文件中含有标签,该属性可忽略        icon: nativeImage.createFromPath("public/favicon.ico"), // "string" || nativeImage.createFromPath("public/favicon.ico")从位于 path 的文件创建新的 NativeImage 实例        webPreferences: { // 网页功能设置            webviewTag: true, // 是否使用<webview>标签 在一个独立的 frame 和进程里显示外部 web 内容            webSecurity: false, // 禁用同源策略            preload: path.join(__dirname, "preload.js"),            nodeIntegration: true // 是否启用node集成 渲染进程的内容有访问node的能力,建议设置为true, 否则在render页面会提示node找不到的错误        }    })      // 加载应用 --打包react应用后,__dirname为当前文件路径    // mainWindow.loadURL(url.format({    //   pathname: path.join(__dirname, "./build/index.html"),    //   protocol: "file:",    //   slashes: true    // }));         // 因为我们是加载的react生成的页面,并不是静态页面    // 所以loadFile换成loadURL。    // 加载应用 --开发阶段  需要运行 yarn start    mainWindow.loadURL("http://localhost:3000");     // 解决应用启动白屏问题    mainWindow.on("ready-to-show", () => {        mainWindow.show();        mainWindow.focus();    });     // 当窗口关闭时发出。在你收到这个事件后,你应该删除对窗口的引用,并避免再使用它。    mainWindow.on("closed", () => {        mainWindow = null;    });        // 在启动的时候打开DevTools    mainWindow.webContents.openDevTools()} app.allowRendererProcessReuse =true; // This method will be called when Electron has finished// initialization and is ready to create browser windows.// Some APIs can only be used after this event occurs.app.whenReady().then(() =>{    console.log("qpp---whenready");    createWindow();}) // Quit when all windows are closed.app.on("window-all-closed", function () {    // On macOS it is common for applications and their menu bar    // to stay active until the user quits explicitly with Cmd + Q    console.log("window-all-closed");    if (process.platform !== "darwin") app.quit()}) app.on("activate", function () {    // On macOS it"s common to re-create a window in the app when the    // dock icon is clicked and there are no other windows open.    if (BrowserWindow.getAllWindows().length === 0) createWindow()}) // In this file you can include the rest of your app"s specific main process// code. You can also put them in separate files and require them here.
  package.json
  这时候我们来修改 package.json  文件。配置启动文件,添加 main  字段,我们这里也就是main.js文件。如果没有添加,Electron 将尝试加载包含在package.json  文件目录中的index.js  文件。配置运行命令,使用 "electron": "electron ."  区别于react的启动命令 "start": "react-scripts start", 安装concurrently:  yarn add concurrently  {    ...    "main": "main.js", // 配置启动文件  	"homepage": ".", // 设置应用打包的根路径    "scripts": {        "start": "react-scripts start",  // react 启动命令        "build": "react-scripts build",        "test": "react-scripts test",        "eject": "react-scripts eject",        "electron": "electron .",  // electron 启动命令        "dev": "concurrently "npm run start" "npm run electron""    },}
  preload.js window.addEventListener("DOMContentLoaded", () => {    const replaceText = (selector, text) => {        const element = document.getElementById(selector)            if (element) element.innerText = text    }      for (const dependency of ["chrome", "node", "electron"]) {        replaceText(`${dependency}-version`, process.versions[dependency])    }})
  此时的工程架构
  2.5 运行electron项目先 yarn start   然后再开一个终端yarn electron  或者是 npm run dev
  其实我们就可以看出Electron就是一个应用套了一个谷歌浏览器壳子,然后里面是前端页面。 2.6 打包项目
  使用 electron-packager 依赖: yarn add --dev electron-packager
  package.json配置打包命令: "package": "electron-packager . bleak-electron-app --platform=win32 --arch=x64 --overwrite --electron-version=18.1.0 --icon=./public/favicon.ico"
  配置解释: electron-packager <应用目录> <应用名称> <打包平台> <架构x86 还是 x64> <架构> <electron版本> <图标>overwrite 如果输出目录已经存在,替换它
  然后运行命令: yarn package
  打包时间慢的话可按照下面两种方式优化: 方法1:在执行electron-packager前先运行set ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/方法2:在electron-packager命令行加入参数--download.mirrorOptions.mirror=https://npm.taobao.org/mirrors/electron/(Windows x64)完整版如下:electron-packager . bleak-electron-app --platform=win32 --arch=x64 --overwrite --electron-version=18.0.4 --download.mirrorOptions.mirror=https://npm.taobao.org/mirrors/electron/
  然后运行 bleak-electron-app-win32-x64  里面的exe文件就可以了。
  3. 自动刷新页面
  当你用react开发的时候,网页内容会自动热更新,但是electron窗口的main.js中代码发生变化时不能热加载。
  安装插件electron-reloader: yarn add --dev electron-reloadernpm install --save-develectron-reloader
  然后在路口引用插件: const reloader = require("electron-reloader")reloader(module)
  就可以实现electron插件热更新。 4. 主进程和渲染进程
  Electron运行package.json的main脚本的进程称为 主进程 。在主进程中运行的脚本通过创建web页面来展示用户节面,一个Electron应用总是有且只有一个主进程。
  由于Electron使用了Chromium来展示web页面,所以Chromium的多进程架构也被使用到,每个Electron钟大哥web页面运行在它的叫 渲染进程 的进程中。
  在普通的浏览器中,web页面无法访问操作系统的原生资源。然而Electron的用户在Node.js的API支持下可以在页面中和操作系统进行一些底层交互。
  ctrl + shift + i 打开渲染进程调试(devtools)
  默认打开调试: // 在启动的时候打开DevToolsmainWindow.webContents.openDevTools()5.定义原生菜单、顶部菜单5.1 自定义菜单
  可以使用Menu菜单来创建原生应用菜单和上下文菜单。 首先判断是什么平台,是mac还是其他: const isMac = process.platform === "darwin"创建菜单模板:
  其是由一个个MenuItem组成的,可以在菜单项官网API查看。 const template = [  // { role: "appMenu" }  // 如果是mac系统才有  ...(isMac ? [{    label: app.name,    submenu: [      { role: "about" },      { type: "separator" },      { role: "services" },      { type: "separator" },      { role: "hide" },      { role: "hideOthers" },      { role: "unhide" },      { type: "separator" },      { role: "quit" }    ]  }] : []),  // { role: "fileMenu" }  {    label: "文件",    submenu: [      isMac ? { role: "close" } : { role: "quit", label: "退出" }    ]  },  // { role: "editMenu" }  {    label: "编辑",    submenu: [      { role: "undo", label: "撤消" },      { role: "redo", label: "恢复" },      { type: "separator" },      { role: "cut", label: "剪切" },      { role: "copy", label: "复制" },      { role: "paste", label: "粘贴" },      ...(isMac ? [        { role: "pasteAndMatchStyle" },        { role: "delete" },        { role: "selectAll" },        { type: "separator" },        {          label: "Speech",          submenu: [            { role: "startSpeaking" },            { role: "stopSpeaking" }          ]        }      ] : [        { role: "delete", label: "删除" },        { type: "separator" },        { role: "selectAll", label: "全选" }      ])    ]  },  // { role: "viewMenu" }  {    label: "查看",    submenu: [      { role: "reload", label: "重新加载" },      { role: "forceReload", label: "强制重新加载" },      { role: "toggleDevTools", label: "切换开发工具栏" },      { type: "separator" },      { role: "resetZoom", label: "原始开发工具栏窗口大小" },      { role: "zoomIn", label: "放大开发工具栏窗口"},      { role: "zoomOut", label: "缩小开发工具栏窗口" },      { type: "separator" },      { role: "togglefullscreen", label:"切换开发工具栏全屏" }    ]  },  // { role: "windowMenu" }  {    label: "窗口",    submenu: [      { role: "minimize", label:"最小化" },      ...(isMac ? [        { type: "separator" },        { role: "front" },        { type: "separator" },        { role: "window" }      ] : [        { role: "close", label: "关闭" }      ])    ]  },  {    role: "help",    label: "帮助",    submenu: [      {        label: "从Electron官网学习更多",        click: async () => {          const { shell } = require("electron")          await shell.openExternal("https://electronjs.org")        }      }    ]  }]根据模板创建menu: const menu = Menu.buildFromTemplate(template)设置菜单: Menu.setApplicationMenu(menu)5.2 给菜单定义点击事件
  可以通过 click  属性来设置点击事件5.3 抽离菜单定义
  创建一个menu.js: const {app, Menu } = require("electron") const isMac = process.platform === "darwin" const template = [  // { role: "appMenu" }  // 如果是mac系统才有  ...(isMac ? [{    label: app.name,    submenu: [      { role: "about" },      { type: "separator" },      { role: "services" },      { type: "separator" },      { role: "hide" },      { role: "hideOthers" },      { role: "unhide" },      { type: "separator" },      { role: "quit" }    ]  }] : []),  // { role: "fileMenu" }  {    label: "文件",    submenu: [      isMac ? { role: "close" } : { role: "quit", label: "退出" }    ]  },  // { role: "editMenu" }  {    label: "编辑",    submenu: [      { role: "undo", label: "撤消" },      { role: "redo", label: "恢复" },      { type: "separator" },      { role: "cut", label: "剪切" },      { role: "copy", label: "复制" },      { role: "paste", label: "粘贴" },      ...(isMac ? [        { role: "pasteAndMatchStyle" },        { role: "delete" },        { role: "selectAll" },        { type: "separator" },        {          label: "Speech",          submenu: [            { role: "startSpeaking" },            { role: "stopSpeaking" }          ]        }      ] : [        { role: "delete", label: "删除" },        { type: "separator" },        { role: "selectAll", label: "全选" }      ])    ]  },  // { role: "viewMenu" }  {    label: "查看",    submenu: [      { role: "reload", label: "重新加载" },      { role: "forceReload", label: "强制重新加载" },      { role: "toggleDevTools", label: "切换开发工具栏" },      { type: "separator" },      { role: "resetZoom", label: "原始开发工具栏窗口大小" },      { role: "zoomIn", label: "放大开发工具栏窗口"},      { role: "zoomOut", label: "缩小开发工具栏窗口" },      { type: "separator" },      { role: "togglefullscreen", label:"切换开发工具栏全屏" }    ]  },  // { role: "windowMenu" }  {    label: "窗口",    submenu: [      { role: "minimize", label:"最小化" },      ...(isMac ? [        { type: "separator" },        { role: "front" },        { type: "separator" },        { role: "window" }      ] : [        { role: "close", label: "关闭" }      ])    ]  },  {    role: "help",    label: "帮助",    submenu: [      {        label: "从Electron官网学习更多",        click: async () => {          const { shell } = require("electron")          await shell.openExternal("https://electronjs.org")        }      }    ]  }] const menu = Menu.buildFromTemplate(template)Menu.setApplicationMenu(menu)
  然后在 main.js  中createWindow  的方法使用require  调用:const createWindow = () => {    ......    require("./menu")    ......}5.4 自定义顶部菜单
  我们可以自定义顶部菜单,通过以下两个步骤进行: 先通过frame创建无边框窗口。 function createWindow () {    const mainWindow = new BrowserWindow({        ......        frame: false    })    }然后再通过前端页面布局设置顶部菜单
  如果想让顶部菜单支持拖拽,可以加如下css: -webkit-app-region: drag;5.5 在渲染进程中使用主进程方法remote和electron(点击创建新窗口)
  我们想要通过 remote 来使用主进程方法和功能。 首先要安装 @electron/remote  yarn add @electron/remote在主进程main.js中配置remote: const remote = require("@electron/remote/main")remote.initialize() const createWindow = () => {    let mainWindow = new BrowserWindow({        ......        webPreferences: { // 网页功能设置        	......            nodeIntegration: true, // 是否启用node集成 渲染进程的内容有访问node的能力,建议设置为true, 否则在render页面会提示node找不到的错误            contextIsolation : false, //允许渲染进程使用Nodejs        }    })    remote.enable(mainWindow.webContents)}在渲染进程中使用remote的BrowserWindow:App.tsx import React from "react"// 使用electron的功能// const electron = window.require("electron")// 使用remoteconst { BrowserWindow } = window.require("@electron/remote") export default function App() {  const openNewWindow = () => {    new BrowserWindow({      width:500,      height:500    })  }   return (          App              <button onClick={openNewWindow}>点我开启新窗口</button>            )}
  我们想要通过使用electron提供给渲染进程的API: const electron = window.require("electron")
  然后从electron中提取方法。 5.6 点击打开浏览器
  使用electron中的shell可以实现此功能: import React from "react"// 使用electron的功能// const electron = window.require("electron")// 使用remote// const { BrowserWindow } = window.require("@electron/remote")// 使用shellconst { shell } = window.require("electron") export default function App() {  const openNewWindow = () => {    shell.openExternal("https://www.baidu.com")  }   return (          App              <button onClick={openNewWindow}>点我开启新窗口打开百度</button>            )}6. 打开对话框读取文件6.1 读取文件
  主进程中的dialog模块可以显示用于打开和保存文件、警报等的本机系统对话框。
  因为dialog模块属于主进程,如果我们在渲染进程中需要使用则需要使用remote模块。
  App.tsx import React,{ useRef } from "react"// 使用electron的功能// const electron = window.require("electron") // 使用remote// const remote = window.require("@electron/remote")// const { BrowserWindow } = window.require("@electron/remote")const { dialog } = window.require("@electron/remote") // 使用shellconst { shell } = window.require("electron") // 使用fsconst fs = window.require("fs") export default function App() {  // ref   const textRef = useRef<HTMLTextAreaElement | null>(null)   const openNewWindow = () => {    shell.openExternal("https://www.baidu.com")  }   const openFile = () => {    const res = dialog.showOpenDialogSync({      title: "读取文件", // 对话框窗口的标题      buttonLabel: "读取", // 按钮的自定义标签, 当为空时, 将使用默认标签。      filters: [ // 用于规定用户可见或可选的特定类型范围        //{ name: "Images", extensions: ["jpg", "png", "gif", "jpeg", "webp"] },        //{ name: "Movies", extensions: ["mkv", "avi", "mp4"] },        { name: "Custom File Type", extensions: ["js"] },        { name: "All Files", extensions: ["*"] },      ]    })    const fileContent:string  = fs.readFileSync(res[0]).toString();    (textRef.current as HTMLTextAreaElement).value = fileContent  }   return (          App Test              <button onClick={openNewWindow}>点我开启新窗口打开百度</button>                    <button onClick={openFile}>打开文件</button>        <textarea ref={textRef}></textarea>            )}6.2 保存文件
  保存文件需要使用dialog函数里的 showSaveDialogSync  ,与之前的读取文件所用到的showOpenDialogSync  类似:const saveFile = () => {    const res = dialog.showSaveDialogSync({        title:"保存文件",        buttonLable: "保存",        filters: [            { name: "index", extensions: ["js"]}        ]    })    fs.writeFileSync(res, textRef.current?.value)}7. 定义快捷键7.1 主线程定义
  引入 globalShortcut  const {app, BrowserWindow, nativeImage, globalShortcut } = require("electron")
  注册快捷键打印字符串、窗口最大化、窗口最小化、关闭窗口。 const createWindow = () => {    ......    // 注册快捷键    globalShortcut.register("CommandOrControl+X", () => {        console.log("CommandOrControl + X is pressed")    })     globalShortcut.register("CommandOrControl+M", () => {        mainWindow.maximize()    })     globalShortcut.register("CommandOrControl+T", () => {        mainWindow.unmaximize()    })     globalShortcut.register("CommandOrControl+H", () => {        mainWindow.close()    })     // 检查快捷键是否注册成功    // console.log(globalShortcut.isRegistered("CommandOrControl+X"))} // 将要退出时的生命周期,注销快捷键app.on("will-quit", () => {    // 注销快捷键    globalShortcut.unregister("CommandOrControl+X")    // 注销所有快捷键    globalShortcut.unregisterAll()})7.2在渲染进程中定义
  通过retmote来定义 const { globalShortcut } = window.require("@electron/remote")  globalShortcut.register("Ctrl+O", () => {    console.log("ctrl+O is pressed.")})8. 主进程和渲染进程通讯
  在渲染进程使用ipcRenderer,主进程使用ipcMain,可以实现主进程和渲染进程的通讯:
  App.tsx ......import React,{ useState, useRef } from "react"const { shell, ipcRenderer } = window.require("electron")export default function App() {    // state  	const [windowSize, setWindowSize] = useState("max-window")    ......    // 传参    const maxWindow = () => {        ipcRenderer.send("max-window", windowSize);        if(windowSize === "max-window") {            setWindowSize("unmax-window")        } else {            setWindowSize("max-window")        }    }        ......        return (                                                        <button onClick={maxWindow}>与主进程进行通讯,窗口最大化或取消窗口最大化</button>                                                        )}
  main.js const {app, BrowserWindow, nativeImage, globalShortcut, ipcMain } = require("electron")const createWindow = () => {    let mainWindow = ......    ......    // 定义通讯事件    ipcMain.on("max-window", (event, arg) => {        if(arg === "max-window") {            mainWindow.maximize()        } else if (arg === "unmax-window") {            mainWindow.unmaximize()        }    })    ......}......
  原文链接:Electron结合React和TypeScript进行开发 - bleaka - 博客园</pre><hr>
<div class="middle_list"><a href="at_135889.html">避免二次感染,提醒中老年人多吃5种高叶酸菜,助身体恢复</a>眼看着春节快到了,不少人已是阳康,这时候最怕的就是二次感染,什么叫二次感染?二次感染就是相当于一次新的感染,是痊愈后的再次感染,一般而言,二次感染与首次感染的症状没有太大区别。如果<a href="at_135890.html">油中之王茶油,为何现在几乎没人吃了?茶油对身体有什么危害</a>茶油为什么现在没有人食用了?十几年前,食用茶油的人还是很多的,但是,在今天,土茶油不能食用的呼声很高。因为土茶油不卫生,含有害物质,越土的茶油越不健康,这是真的吗?有人认为乡下买的<a href="at_135891.html">水滴筹严格风控,更好地帮助困难大病患者</a>自大病筹款平台诞生以来,发展至今,已经日趋成熟,风控更加严格,能够最大程度避免虚假夸大病情等现象的出现。比如水滴筹,其运用互联网科技优势,引入NLPOCR推荐算法核身鉴权等多项AI<a href="at_135892.html">宫寒月经乱怀不上?1张方,2个注意事项,给子宫烤烤火</a>如果你以为宫寒只是子宫寒冷?那你就是真的错了!宫寒到底是什么?其实这里的宫寒并不是很多人以为的子宫寒冷手脚怕冷,也并不是我们理解的温度上的寒冷。宫寒并不是一种病,而是多种异常症状的<a href="at_135893.html">立讯精密再陷砍单传闻,苹果成果链甜蜜负担?</a>2023年刚开年,果链一哥立讯精密工业股份有限公司(下称立讯精密)就再次陷入苹果砍单传闻。1月4日,立讯精密开盘后股价迅速跳水,截至收盘,触及跌停,报跌停价28。37元,跌幅为9。<a href="at_135894.html">萝卜是胃病加速器吗?医生建议这些伤胃食物要远离!</a>胃作为人体重要的消化吸收器官,有着很重要的作用,帮助消化所受到的食物,吸收其中的营养成分,维持人体正常的功能运转。但是在现在生活中,越来越多的年轻人却由于日常饮食的不注意,胃都有一<a href="at_135895.html">股骨头坏死患者冬天要注意保暖</a>今天就是小寒了,清晨或者傍晚人们能明显感觉到寒气打在身体上,冬天的低气温对股骨头坏死患者无疑是一种考验。所以股骨头坏死患者在冬天要注意保暖,适当增加衣物。股骨头坏死患者在冬天一定要<a href="at_135896.html">乙肝朋友们,这些食物助你肝血充足,睡得香!</a>乙肝战友们经常会出现的一个问题就是失眠,失眠不仅仅影响人第二天的精神状态,时间久了经常熬夜也会影响肝脏的健康,从中医角度讲,夜晚11点3点的阶段是肝脏新陈代谢的重要时间段,因此一定<a href="at_135897.html">萝卜是胃病加速器?医生警告冬季养胃,远离这些伤胃食物!</a>胃是体内的消化器官,食物从嘴巴里进入,经过食管会进入胃里,然后胃会分泌胃酸,不断蠕动的胃开始对食物进行消化和吸收。对于胃部的保护很重要,不管免疫力好与否,都需要重视日常饮食以及胃部<a href="at_135898.html">C罗未进名单无缘首秀!利雅得胜利首发塔利斯卡奥斯皮纳出战</a>直播吧1月6日讯北京时间1月6日23点,沙特职业联赛第12轮,领头羊利雅得胜利主场迎战阿尔泰。利雅得胜利公布首发,C罗未进大名单无缘首秀。据此前沙特媒体沙特体育报消息,C罗的球员转<a href="at_135899.html">小寒隆冬至,这些养生要点了解一下</a>小寒时处二三九天寒地冻冷到抖1月5日我们迎来了小寒节气养生达人如何在小寒时节保健养生长春市中医院治未病中心医生这样说起居防寒保暖小寒是一年中最为寒冷的时节,所以保暖是第一要务。冬季</div>
<div class="middle_page"><a href="/udt/ls_13239.html"><<<</a><a href="/udt/ls_13238.html"><<</a><a href="/udt/ls_13237.html"><</a><span>-</span><a href="/udt/ls_13235.html">></a><a href="/udt/ls_13234.html">>></a><a href="/udt/ls_13233.html">>>></a></div></div>
<div class="middle_right"><a href="https://www.vkhz.com/think.html"><img src="/static/vkhz.png" width="100%"></a><a href="at_681698.html">国乒再次出征,林高远将参加WTT常规赛!世乒赛,王曼昱是一单?</a>国乒再次出征,林高远也将参加WTT常规挑战赛突尼斯站比赛。虽然在WTT冠军赛上,林高远在105的情况下,被张本智和逆转,但是国乒并没有放弃他。作为资深球迷,我们希望林高远战胜心魔,<a href="at_681699.html">这两款手机各方面都很均衡,性价比也很不错,很推荐入手</a>选择手机的时候,需要考虑四大方面,手机的性能屏幕素质续航拍照,可能会有很多数码小白会很疑惑,不知道要怎么选择,今天小黑就为大家推荐两款各方面都很均衡的手机。第一款vivoX70pr<a href="at_681700.html">京东宠物发布2022十大宠物主粮排行榜首创选粮助手服务全面解决宠物主选粮焦虑</a>7月23日,京东宠物发布2022京东宠物十大狗粮排行榜和2022京东宠物十大猫粮排行榜。两份榜单依托京东宠物推出的选粮助手服务,根据宠物食品的国家标准美国饲料管理协会宠物粮标准(A<a href="at_681701.html">A股大盘缩量收出实体阴线,明日大盘走势预测</a>半城烟雨半城风,半树桃花半飘零。繁华落尽霓虹匿,唯有相思寄晨钟。今日大盘再次出现了小幅回落,从盘口来看,今日下跌19。58点,跌幅0。6。红盘个股比较少,绿盘个股明显增多。新冠监测<a href="at_681702.html">6架C919成功试飞后,痛失大单的波音示好对华关系超越地缘政治</a>波音公司想在中国市场来个亡羊补牢,不知是否为时已晚。据观察者网7月25日援引外媒的消息称,波音东北亚地区销售及市场高级副总裁穆尼尔在参加英国范堡罗航展时,针对波音公司在中国的业务发<a href="at_681703.html">空难重击过4个月后,东航集团董事长退职!尚未到任期曾临危受命,带集团止亏增盈双上市</a>在距离自己任期还剩四个月的时候,刘绍勇率先卸下了东航集团董事长的职务。7月23日晚,有媒体曝出东航集团有限公司已经召开会议,宣布中央组织部关于董事长刘绍勇退职的决定。记者联系东航集<a href="at_681704.html">4S店之王上半年净利降9成!多番出售子公司偿债,危机仍难解</a>7月26日消息,近日,4S店之王庞大汽贸披露了半年度业绩预减公告。预计2022年上半年实现归属于上市公司股东的净利润为2000万至3000万元,同比下降94。85至96。57。对于<a href="at_681705.html">A股明天(7月26日)大盘走势简析等待确认变盘的信号出现</a>今天的A股平开后就一路震荡下跌,昨天给大家指出了大盘走势出现的一个强烈的变盘信号,其实是一个短期趋势的转变,也就预示着短线的调整将会持续,毕竟是对前期近3个月的反弹走势的一个调整,<a href="at_681706.html">2022年公积金调整开始!到手工资又变少了?</a>2022年已过半,又将迎来一年一度的公积金调整环节!多地陆续发布公告,7月起,用人单位将为员工调整公积金缴存基数比例。这将决定新的公积金缴存年度(今年7月1日次年6月30日),单位<a href="at_681707.html">银行定期存款,有本子和无本子有何区别?各位朋友需熟知</a>俗话说得好手有余粮而心不慌。存钱自古以来就是中国人的习惯和传统。近年来,银行制度的不断发展,使得其业务更加的广泛和完善,因此越来越多的人选择在银行存款。国家也进行了非常严格的调整和<a href="at_681708.html">(国际图文互动)通讯南非民间观鲸达人快乐助科研</a>(配本社同题文字稿)7月13日,在南非开普敦,人们在岸边看鲸鱼。新华社记者吕天然摄6月15日,在南非开普敦,鲸鱼在海中游弋。新华社记者吕天然摄6月15日,在南非开普敦,鲸鱼在海中游<div class="middle_right_youlian"></div></div></div>
</body></html>