微前端——无界wujie

B站课程视频
课程视频

课程课件笔记:
1.微前端

2.无界

现有的微前端框架:iframe、qiankun、Micro-app(京东)、EMP(百度)、无届

前置

初始化

新建一个文件夹
1.通过npm i typescript -g安装ts
2.然后可以使用tsc --init初始化项目,这样项目目录下会有tsconfig.json配置文件
3.再新建index.ts
4.使用tsc -w命令可以实时的编译index.ts出一个index.js文件
5.通过index.html引入index.js即可

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./index.js"></script>
</head>
<body>
</body>
</html>

webComponents初使用

主要是为了样式隔离

wu-jie初体验

index.ts文件中书写

// webComponents 的写法
window.onload = () => {// 初始化class Wujie extends HTMLElement {// 类的基本用法constructor() {super()// this.attachShadow创建shadowdom并打开就具有样式隔离的性质,不会影响外层的样式let dom = this.attachShadow({mode: 'open'})// 获取templatelet template = document.querySelector('#wujie') as HTMLTemplateElement// 并绑定,这里是把template的内容深度克隆一份给dom,而不是直接给,true表示深度克隆dom.appendChild(template.content.cloneNode(true))// 这样就把template的内容渲染到了<wu-jie></wu-jie>的组件里面console.log(this.getAttr('url'), this.getAttr('age'))}// 获取传参this.getAttribute 传入属性名即可private getAttr(attr: string) {return this.getAttribute(attr)}}// webComponents挂载,注意名字不能启成驼峰的但是-横线连接可以,第二个参数是上面类的名字// 类似vue组件  原生js写的一个组件 可以在html中使用了<wu-jie></wu-jie>window.customElements.define('wu-jie', Wujie)
}

在上述建立的index.html中书写

<body><!-- 相当于组件,也可以传参 --><wu-jie url='xxxxx' age='18'></wu-jie><div>我是外层的div</div><template id="wujie"><div>我是 template 里面的div</div><style>div{background: red;}</style></template>
</body>

无届的三个生命周期

//生命周期自动触发有东西插入
connectedCallback () {console.log('类似于vue 的mounted');
}
//生命周期卸载
disconnectedCallback () {console.log('类似于vue 的destory');
}
//跟watch类似
attributeChangedCallback (name:any, oldVal:any, newVal:any) {console.log('跟vue 的watch类似,有属性发生变化自动触发');
}

pnpm介绍

1.全局安装npm i pnpm -g
2.使用 pnpm -v可以查看版本号
3.pnpmnpm的优势,在pnpm中文网的动机这样写pnpm官网
在这里插入图片描述
简单来说就是,但有100个vue项目,每个项目都会去安装相应的依赖包,这样导致磁盘的缩小和安装速度慢(每次都会重新下载依赖包),很麻烦。
但是pnpm使用软链接硬链接仓库解决

硬链接

1.使用cmd查看提示,表示 /H就是硬链接
在这里插入图片描述

2.创建命令含义 mklink /H 硬链接的名字 通过谁创建
例如:在pnpm文件目录下建立index.js文件,并通过mklink /H ying.js index.js创建了硬链接
在这里插入图片描述
3.并且目录下多出了一个ying.js
在这里插入图片描述

4.然后打开文件发现ying.js中内容和index.js中一样
在这里插入图片描述
5.而且当修改index.js中的内容时,ying.js中的内容会跟着修改,因为他们共享的同一个磁盘地址

软链接(符号链接)

1.创建软链接需要管理员权限,所以管理员打开cmd后进入目录可以使用cd ../../等回退到根目录下,然后直接 D: 进入相应盘,再cd命令
2.默认就是软链接 mklink ruan.js index.js 即可,不用加任何修饰符
在这里插入图片描述
3.成功创建后VScode中会有一个标志
在这里插入图片描述
4.且文件管理器中查看也是一个0字节的,因为他只记录一个路径(快捷方式,并不会占用资源),点击会跳转,指向的还是index.js
在这里插入图片描述

pnpm如何利用硬链接、软链接解决上述问题

1.使用pnpm init命令创建package.json
2.以安装vue包为例,使用pnpm i vue 安装vue依赖,可以看到node_modules下面有vue的软链接(快捷方式,地址指向)
在这里插入图片描述
3.实际上上述软链接指向在.pnpm包下找到真正的vue@3.3.13的包下面的vue文件夹,这个vue硬链接指向.pnpm store
在这里插入图片描述
4.实际上就对应了pnpm官网的这张图,非扁平化的方式(可能嵌入,因为这个库可能还依赖其他库,这样依次来)
在这里插入图片描述

绿色黄色实线为软链接、红色虚线为硬链接
在这里插入图片描述

pnpm的CLI命令管理

假设你之前使用的npm 安装包,会生成一个package-lock.json,或者使用yarn安装过,会生成一个yarn.lock

但是你再通过pnpm import命令 他会把你的上述的软件包管理器的 lockfile 生成 pnpm-lock.yaml文件

monorepo项目

创建monorepo项目目录

1.使用命令npm init vue创建vue项目,并创建项目名为main
2.创建web文件目录存放子应用
3.创建vue子应用,使用npm init vite选择vue+typescript
4.创建react子应用,使用npm init vite选择react+typescript
5.在web文件夹下有多个子应用,分别安装有点繁琐,所以在monorepo文件夹下使用命令pnpm init生成文件,并手动创建pnpm-workspace.yaml文件和配置。配置

官网是:
packages:# all packages in direct subdirs of packages/- 'packages/*'# all packages in subdirs of components/- 'components/**'# exclude packages that are inside test directories- '!**/test/**'替换为自己的目录
packages:# all packages in direct subdirs of packages/- 'main/*'# all packages in subdirs of components/- 'web/**'

此时目录如下:
在这里插入图片描述
6.替换好pnpm-workspace.yaml之后可以在根目录直接pnpm i即可自动为所有的项目安装包
最外层根目录下的node_modules是所有项目公共的包,而vue项目或者react项目里面的node_modules是他们单独所需要的,这样结构更加清晰。
在这里插入图片描述

子项目启动:

假设这时候我们要跨级执行命令,想要执行react-demo项目中package.jsondev命令,可以使用pnpm -F react-demo dev,其中F是过滤filter

子模块复用:

1.新建目录common下,并进入,想要common目录下的东西其余子项目(vue、react等都可以使用)
2.使用pnpm init初始化生成package.json文件。在pnpm-workspace.yaml中写

packages:# all packages in direct subdirs of packages/- 'main/*'# all packages in subdirs of components/- 'web/**'- 'common'

3.安装axios包了pnpm i axios
在这里插入图片描述
3.新建index.ts,编写一些公共代码

import axios from 'axios'// 公共的提取出来
export const a = axios.get('xxx')

4.进入main目录使用命令pnpm -F main add common则把common添加进main项目的依赖中,查看main/package.json文件里面有
在这里插入图片描述
5.然后就可以在main/src/main.ts中引入

import { a } from 'common'

6.同理,也可以去给react-demo项目添加或者vue-demo添加:pnpm -F vue-demo add common,一样查看那个package.json有common包,然后可以导入进行使用

无届

安装

1.使用pnpm i wujie,在main.ts中引入wujie并配置启动的参数

import { startApp } from 'node_modules/wujie/esm/index'
// 启动的参数
startApp({name, url, el})

2.如果是vue项目,可以直接安装npm i wujie-vue3进行安装

import Wujie from 'wujie-vue3'
app.use(router).use(Wujie)

3.然后分别启动好子应用,记录端口就可以在App.vue中使用了

<template><div><h1>这是主应用</h1><!-- 分别是子应用,子应用启动之后各自的端口 --><WujieVue url="http://127.0.0.1:5174" name="vue3"></WujieVue><WujieVue url="http://127.0.0.1:5175" name="react"></WujieVue></div>
</template>

在main.ts中,全部代码如下:

import './assets/main.css'import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import Wujie from 'wujie-vue3' // 引入一下对应的框架
import { preloadApp } from 'wujie'const app = createApp(App)app.use(router).use(Wujie) // 注册无界
app.mount('#app')// exac预加载为true即可,那么components/react.vue和vue3.vue就会有url
preloadApp({ name: "vue3", url: "http://127.0.0.1:5173", exec: true})
preloadApp({ name: "react", url: "http://127.0.0.1:5174", exec: true})

封装无届

1.创建的目录

封装无届

1.创建的目录文件如下:
其中使用pnpm init创建package.json
使用tsc --init创建 tsconfig.json
在这里插入图片描述
2.使用pnpm i wujie安装无届
3.使用pnpm i vue -D把vue装在开发环境中
4.安装webpack,使用pnpm i webpack webpack-cli -D
5.安装typescript,使用 pnpm i typescript -D
6.安装typescript解析器,使用pnpm i ts-loader -D

书写相关配置代码

配置代码部分可以看源码参照下面的代码

写完后使用 npm run lib 打包

1.在env.d.ts中书写

import { defineComponent, h, getCurrentInstance, onMounted, watch, onBeforeUnmount } from 'vue'
import type { App, PropType } from 'vue'
import { Props } from './type'
import { startApp, bus } from 'wujie'// 函数式定义组件
const wujie = defineComponent({props: {width: { type: String, default: "" },height: { type: String, default: "" },name: { type: String, default: "", required: true },loading: { type: HTMLElement, default: undefined },url: { type: String, default: "", required: true },sync: { type: Boolean, default: undefined },prefix: { type: Object, default: undefined },alive: { type: Boolean, default: undefined },props: { type: Object, default: undefined },attrs: { type: Object, default: undefined },replace: { type: Function as PropType<Props['replace']>, default: undefined },fetch: { type: Function as PropType<Props['fetch']>, default: undefined },fiber: { type: Boolean, default: undefined },degrade: { type: Boolean, default: undefined },plugins: { type: Array as PropType<Props['plugins']>, default: null },beforeLoad: { type: Function as PropType<Props['beforeLoad']>, default: null },beforeMount: { type: Function as PropType<Props['beforeMount']>, default: null },afterMount: { type: Function as PropType<Props['afterMount']>, default: null },beforeUnmount: { type: Function as PropType<Props['beforeUnmount']>, default: null },afterUnmount: { type: Function as PropType<Props['afterUnmount']>, default: null },activated: { type: Function as PropType<Props['activated']>, default: null },deactivated: { type: Function as PropType<Props['deactivated']>, default: null },},setup(props, { emit }) {// 读取当前组件实例// this.$refs.wujie // 在vue2中可以通过this获取当前组件实例const instance = getCurrentInstance() // vue3中通过getCurrentInstance获取组件实例// 封装启动函数const init = () => {// startApp({name, url, el})//初始化无界startApp({name: props.name,url: props.url,el: instance?.refs.wujie as HTMLElement,loading: props.loading,alive: props.alive,fetch: props.fetch,props: props.props,attrs: props.attrs,replace: props.replace,sync: props.sync,prefix: props.prefix,fiber: props.fiber,degrade: props.degrade,plugins: props.plugins,beforeLoad: props.beforeLoad,beforeMount: props.beforeMount,afterMount: props.afterMount,beforeUnmount: props.beforeUnmount,afterUnmount: props.afterUnmount,activated: props.activated,deactivated: props.deactivated,})}watch([props.name, props.url], () => {init() // 如果发生变化就重新执行startApp})const handlerEmit = (event:string, ...args:any[]) => {emit(event, ...args)}onMounted(() => {// 发布订阅模式bus.$onAll(handlerEmit) init()})onBeforeUnmount(() => {bus.$offAll(handlerEmit)})// 定义渲染函数return ()=> h('div', {style: {width: props.width,height: props.height},ref: "wujie" // 方便之后读取})}
})
// install 方法给vue使用的,app.use(router).use(wujie)会调用install
wujie.install = function(app: App) {app.component('WujieVue', wujie)
}export default wujie

2.type.ts中写

import type { plugin } from 'wujie'
type lifecycle = (appWindow: Window) => any;
interface Props {/** 唯一性用户必须保证 */name: string;/** 需要渲染的url */url: string;/** 需要渲染的html, 如果用户已有则无需从url请求 */html?: string;/** 渲染的容器 */loading?: HTMLElement;/** 路由同步开关, false刷新无效,但是前进后退依然有效 */sync?: boolean;/** 子应用短路径替换,路由同步时生效 */prefix?: { [key: string]: string };/** 子应用保活模式,state不会丢失 */alive?: boolean;/** 注入给子应用的数据 */props?: { [key: string]: any };/** js采用fiber模式执行 */fiber?: boolean;/** 子应用采用降级iframe方案 */degrade?: boolean;/** 自定义运行iframe的属性 */attrs?: { [key: string]: any };/** 自定义降级渲染iframe的属性 */degradeAttrs?: { [key: string]: any };/** 代码替换钩子 */replace?: (codeText: string) => string;/** 自定义fetch,资源和接口 */fetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>;/** 子应插件 */plugins: Array<plugin>;/** 子应用生命周期 */beforeLoad?: lifecycle;/** 没有做生命周期改造的子应用不会调用 */beforeMount?: lifecycle;afterMount?: lifecycle;beforeUnmount?: lifecycle;afterUnmount?: lifecycle;/** 非保活应用不会调用 */activated?: lifecycle;deactivated?: lifecycle;
};export { Props } 

3.webpack.config.js中写

const { Configuration } = require('webpack')
const path = require('path')/*** @type {Configuration} //配置智能提示*/const config = {entry: "./src/index.ts", // 入口文件mode: "none",output: {filename: "index.js",path: path.resolve(__dirname, 'lib')},externals: { // 防止打包后的代码包含wujie和vue代码显得过多vue: "vue",wujie: "wujie"},module: {rules: [{test: /\.ts$/,use: "ts-loader"}]}}module.exports = config

SWC和babel

SWC官网
1.swc比babel快20倍,如果是4核情况下,快70倍
使用pnpm add -D @swc/score swc-loader安装命令

2.然后替换webpack.config.js中的use

module: {rules: [{test: /\.ts$/,use: "ts-loader" // babel的ts-loader,换成swc-loader}]}

3.因为swc底层是rust写的,rust性能是js的好几倍所很快

4.然后再打包npm run lib打包后还不能直接使用,
因为前端有很多代码规范,AMD, CMD,CommonJS,ESModule,所以统一配置一个UMD,
5.安装pnpm i -D @swc/cli @swc/core以便使用swc-cli
6.新建配置文件.swcrc

{"$schema": "https://json.schemastore.org/swcrc","jsc": {"parser": {"syntax": "typescript", // js是ecmascript// "jsx": false,// "dynamicImport": false,// "privateMethod": false,// "functionBind": false,// "exportDefaultFrom": false,// "exportNamespaceFrom": false,// "decorators": false,// "decoratorsBeforeExport": false,// "topLevelAwait": false,// "importMeta": false},// "transform": null,"target": "es5","loose": false,"externalHelpers": false,// Requires v1.2.50 or upper and requires target to be es2016 or upper."keepClassNames": false},"minify": false}

7.在根目录的package.json的 scripts中编写打包命令写"esm": "swc src/index.ts -d esm",
8.控制台执行 npm run swc即可打包在esm文件中
9.修改增添package.json中
设定一些版本号和启动的入口

"name": "vuejie-setup",
"version": "0.0.1","main": "lib/index.js", 
"module": "esm/index.js",

添加files

"files": ["lib","esm","index.d.ts"],

10.在根目录下的index.d.ts声明文件中写

// import { bus, preloadApp, destroyApp, setupApp } from "wujie";
import type { App } from 'vue';declare const WujieVue: {// bus: typeof bus;// setupApp: typeof setupApp;// preloadApp: typeof preloadApp;// destroyApp: typeof destroyApp;install: (app: App) => void
};export default WujieVue;

发布包

1.切换镜像 mmp use,输入 npm
2.使用 npm adduser命令,然后输入npm的用户名
在这里插入图片描述
3.使用npm login
4.使用 npm publish发布

使用

1.在MONOREPO项目中切换进主应用cd main
2.命令安装pnpm i vuejie-setup
3.在main.ts中引入import Wujie from 'vuejie-setup'
4.使用npm run dev启动各种主应用或者子应用查看效果

无届的预加载和FPS

1.requestldleCallback函数
MDN的解释
在这里插入图片描述

2.FPS扩展
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

无届的传参

总共三种方法

第一种方法

无届的架构是把JS单独存放在了iframe中,那么iframe可以通过window和父级进行通讯,所以第一种传参就是通过
window.parent.变量名 进行读取。

1.在vue-demo/App.vue中添加按钮,绑定函数获取a

<script setup lang="ts">
const send = () => {alert(window.parent.a) //
}
</script>
<button @click="send">点击</button>

2.在控制台输入变量 var a = '控制台的输入'
3.点击按钮,发现可以弹出
在这里插入图片描述

在这里插入图片描述

第二种方法

通过props 传参,子应用不需要绑定无界,主应用接进来之后会自动捕获vue实例,所以子应用可以访问到无界实例对象获取参数

1.例如在主应用的components/App.vue组件中挂载数据,通过props传参

<template><WujieVue :props="{name: '张三', age: '18'}" url="http://127.0.0.1:5173" name="vue3"></WujieVue>
</template>

2.然后在vue-demo子项目中的App.vue中写JS代码

const send = () => {// alert(window.parent.a) // 第一种方法console.log(window.$wujie) // 第二种方式
}

3.为了防止上述$wujie报错,可以在main.ts中添加

declare global {interface Window {$wujie: {props:  Record<string, any>bus: {$emit: any}}}
}

4.打印的结果如下(可以看到还有bus,第三种方法获取)
在这里插入图片描述
4.上述可以访问props console.log(window.$wujie)进行打印

d第三种方案eventBus发布订阅

可以双向数据传递,直接使用wujie的bus.$on
1.在 主应用的App.vue中通过bus.$on绑定数据

<script lang="ts">
import { bus } from 'wujie'
bus.$on('vue3', (data: any) => {console.log(data, '我是主应用的bus.$on')
})
</script>

2.在子应用vue-demo的App.vue中通过实例直接使用

const send = () => {// alert(window.parent.a)// console.log(window.$wujie.props) // 获取到App.vue下的propswindow.$wujie.bus.$emit('vue3', '我是子应用vuedemo')
}

模块联邦

1.创建文件如下,目录
在这里插入图片描述

2.安装下面四个依赖包
npm i webpack webpack-cli webpack-server html-webpack-plugin -D
在这里插入图片描述
3.书写代码,略,结果如下,总之host里面没有的List数据却通过引入到了remote的数据进行展示
在这里插入图片描述
在这里插入图片描述
4.pnpm run build进行打包host项目下
点开dist/bundle.js,可以看到使用CDN的方式进行引入的
在这里插入图片描述
之前:10个项目引用同一个模块,通过把这个项目发布到npm上面,然后这是个项目可以install这个模块,但是当这个模块发生改变的时候,例如从1.0.0 -> 1.0.1,那么这十个项目得重新下载install一遍
现在的CDN,当你的模块修改了,直接就是最新的版本,通过这个链接,远程调用联邦的技术正是用的这种

报错

1.在tsconfig.app.json中报错:没有 “node” 模块解析策略的情况下,无法指定选项 “-resolveJsonModule”。

修改tsconfig.app.json 文件中 compilerOptions 选项配置 “moduleResolution”: “node”

{"extends": "@vue/tsconfig/tsconfig.dom.json","include": ["env.d.ts", "src/**/*", "src/**/*.vue"],"exclude": ["src/**/__tests__/*"],"compilerOptions": {"composite": true,/** 模块解析策略,ts默认用node的解析策略,即相对的方式导入, 可选值:node、classic* 如果未指定,则 --module commonjs 默认为 node,否则默认为 classic(包括 --module 设置为 amd、system、umd、es2015、esnext 等)* Node 模块解析是 TypeScript 社区中最常用的,推荐用于大多数项目。 * 如果您在 TypeScript 中遇到导入和导出的解析问题,请尝试设置 moduleResolution: “node” 以查看它是否解决了问题。*/"moduleResolution": "node",    "baseUrl": ".","paths": {"@/*": ["./src/*"]}}
}

参考自

一些文件爆红

1.找不到模块“./App.vue”或其相应的类型声明
2.ts.config.app.json找不到文件vue tsconfig tsconfig dom json

如果报错vite找不到之类的,以及奇怪的错误请删除两个子应用重新建立和安装和初始化最外层的包pnpm init

ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL vue-demo@0.0.0 dev: `vite` Exit status 1

一些常用的命令

pnpm i 和 pnpm init

pnpm i是 pnpm install的简写,表示安装包,会根据package.json的包版本进行安装,
pnpm init是初始化一个项目,一般只会在空项目文件下创建package.json一些必要的包

pnpm run dev 和 pnpm run start

前者是开发环境,后者是打包之后的生产环境运行项目

使用脚手架建立项目

因为涉及诸多配置,建议按照vite、webpack官网来看

使用vite脚手架建立vue、react项目

使用webpack脚手架建立vue、react项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java executor spring_Spring+TaskExecutor实例

一 TaskExecutor接口Spring的TaskExecutor接口等同于Java.util.concurrent.Executor接口。 实际上&#xff0c;它存在的主要原因是为了在使用线程池的时候&#xff0c;将对Java 5的依赖抽象出来。 这个接口只有一个方法execute(Runnable task)&#xff0c;它根据线程池的语义和…

小程序居然可以用WXS模拟实现过滤器!

小程序目前官方还没有出过滤器&#xff0c;特别不方便&#xff0c;但是可以用wxs来模拟过滤器&#xff0c;话不多说&#xff0c;直接上代码。当然&#xff0c;不熟悉wxs的可以先看一下 官方文档 1.新建一个filter.wxs的文件我个人建议是一个过滤器写一个wxs&#xff0c;避免引用…

ADF:使用HTTP POST方法进行URL任务流调用

众所周知&#xff0c;可以通过某些URL直接从浏览器或某些外部应用程序调用有限任务流。 如果任务流的属性“ URL invoke”设置为“ url-invoke-allowed”&#xff0c;则启用此功能&#xff0c;该功能通常在集成项目中使用。 通常&#xff0c;客户端&#xff08;或调用者&#x…

java 项目做多级缓存_【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)...

一、缓存当系统的并发量上来了&#xff0c;如果我们频繁地去访问数据库&#xff0c;那么会使数据库的压力不断增大&#xff0c;在高峰时甚至可以出现数据库崩溃的现象。所以一般我们会使用缓存来解决这个数据库并发访问问题&#xff0c;用户访问进来&#xff0c;会先从缓存里查…

Spring MVC:带有CNVR卷的REST应用程序。 3

这是带有CNVR的Spring MVC REST教程的最后一部分。 在这里&#xff0c;我将演示所有这些东西如何工作&#xff0c;这是我在前两部分中开发的。 对于每种类型的CRUD操作&#xff0c;这将分为四个部分&#xff1a;CREATE&#xff0c;READ&#xff0c;UPDATE&#xff0c;DELETE。 …

java 中io的删除文件_总结删除文件或文件夹的7种方法-JAVA IO基础总结第4篇

本文是Java IO总结系列篇的第4篇&#xff0c;前篇的访问地址如下&#xff1a;如果您阅读完成&#xff0c;觉得此文对您有帮助&#xff0c;请给我点个赞&#xff0c;您的支持是我不竭的创作动力。为了方便大家理解&#xff0c;我特意制作了本文对应的视频&#xff1a;总结删除文…

实现小程序canvas拖拽功能

组件地址 https://github.com/jasondu/wx-comp-canvas-drag 实现效果 如何实现 使用canvas使用movable-view标签 由于movable-view无法实现旋转&#xff0c;所以选择使用canvas 需要解决的问题 如何将多个元素渲染到canvas上如何知道手指在元素上、如果多个元素重叠如何知…

H5页面滚动阻尼效果实现

功能描述 要求 页面分为AB两个区域 当手机可视区的底部接触到 “阻尼带” 的时候&#xff0c;有个上拉弹性过程 当上拉到一定阈值程度就直接把B区顶部弹到手机可视区的顶部&#xff0c;让可视区从B区开始显示当上拉程度未到阈值&#xff0c;就回弹复原 当手机可视区从B区向上…

web 前端 html

1&#xff0c;什么是web 在网络中&#xff0c;大量的数据需要有一个载体&#xff0c;而很多人都能够访问这个载体&#xff0c;利用浏览器的这个窗口链接一个有一个载体&#xff0c;这个载体就是网站也就是web的前身。  1&#xff0c;web标准&#xff1a;结构标准&#xff0c;表…

再谈前后端分离

前段时间我针对手头上的项目前端配置进行了反思以及总结并且写了两篇文章: webpack传统后端渲染的项目前端配置, webpack配置之前后端不分离, 很显然这些配置能满足一时的需求, 但是也有不足. 今天继续总结, 这里应该不涉及到具体后端语言, 只对前端配置进行描述. 毕竟配置工程…

Python - day1 借鉴洪卫

一、了解开发语言 1、高级语言&#xff1a;Python&#xff0c;Java&#xff0c;C&#xff0c;C#&#xff0c;PHP&#xff0c;JS&#xff0c;Go&#xff0c;Ruby&#xff0c;SQL&#xff0c;Swift&#xff0c;Perl&#xff0c;Objective-C&#xff0c;R等等&#xff1b; 2、低级…

返回一个二维整数数组最大子数组的和

要求&#xff1a; 1&#xff0c;输入一个二维整形数组&#xff0c;数组里有正数也有负数。 2&#xff0c;二维数组中连续的一个子矩阵组成一个子数组&#xff0c;每个子数组都有一个和, 3&#xff0c;求所有子数组的和的最大值。 设计思路&#xff1a; 参照一维整数数组求解最大…

基于React的表单开发的分析(上)

本文主要讲解后台系统与表单相关的页面开发&#xff0c;并分析如何才能更好地、高效地开发。 技术栈 ReactAntd 背景 Antd 以下我都将Ant Design 简称为 Antd Ant Design是个服务于企业级产品的UI框架&#xff0c;主要可以用于中后台系统,它有基于React、Vue和Angular的实现…

50个Servlet面试问答

Servlet是Java EE的一个非常重要的主题&#xff0c;所有Web应用程序框架&#xff08;例如Spring和Struts&#xff09;都建立在它之上。 这使servlet成为Java访谈中的热门话题。 在这里&#xff0c;我提供了50个servlet面试问题的列表&#xff0c;并提供了答案&#xff0c;以帮…

深入浅出的webpack4构建工具--webpack4+react构建环境(二十)

下面我们来配置下webpack4react的开发环境&#xff0c;之前都是针对webpack4vue的。下面我们也是在之前项目结构的基础之上进行配置下。 首先看下如下是我为 webpack4react 基本的项目结构如下&#xff1a; ### 目录结构如下&#xff1a; demo1 …

Webpack 4进阶--从前的日色变得慢 ,一下午只够打一次包

从前的日色变得慢&#xff0c;车&#xff0c;马&#xff0c;邮件都慢&#xff0c;一生只够爱一个人 -- 《从前慢》 近期在团队项目里把Webpack升级到4.4.1&#xff0c;过程中发现现存的升级文档十分有限&#xff0c;踩了不少坑&#xff0c;好在升级之后提升还算显著&#xff0c…

编码Java时的10个微妙的最佳实践

这是10个最佳实践的列表&#xff0c;这些最佳实践比您的平均Josh Bloch有效Java规则要微妙得多。 尽管Josh Bloch的列表很容易学习&#xff0c;并且涉及日常情况&#xff0c;但此处的列表包含了涉及API / SPI设计的较不常见的情况&#xff0c;但可能会产生很大的影响。 我在编…

Vue 实现微信 jssdk 扫码, 上传图片

流程 1: 配置微信公众号JS域名 2:前端发送URL后台获取JSSDK配置, 后台Service代码如下, 修改2处位置: WeixinUtil.APPID > 当前公众号APPID WeixinUtil.getAccessToken() > 当前公众号access_token public interface IWxJssdkService {Map<String, Object> getJssd…

使用Storm进行可扩展的实时状态更新

在本文中&#xff0c;我将说明如何借助Storm框架以可扩展且无锁定的方式在数据库中维护实时事件驱动流程的当前状态。 Storm是基于事件的数据处理引擎。 它的模型依赖于基本原语&#xff0c;例如事件转换&#xff0c;过滤&#xff0c;聚合……&#xff0c;我们将它们组合成拓扑…

【干货】十分钟读懂浏览器渲染流程

在之前写过的一篇《"天龙八步"细说浏览器输入URL后发生了什么》一文中&#xff0c;和大家分享了从在浏览器中输入网址URL到最终页面展示的整个过程。部分读者向我反馈对于最后的浏览器渲染布局这块不是很清晰&#xff0c;所以本文就浏览器渲染流程单独开篇讲解&#…