首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >微前端——single-Spa

微前端——single-Spa

原创
作者头像
maureen
发布于 2022-10-06 12:15:41
发布于 2022-10-06 12:15:41
3.9K0
举报

一、概念

2018年,single-spa诞生了,single-spa是一个小于5kb(gzip)npm包,用于协调微前端的挂载和卸载。只做两件事: 提供生命周期,并负责调度子应用的生命周期。挟持 url 变化,url 变化时匹配对应子应用,并执行生命周期流程。

用于前端微服务化的JavaScript前端解决方案 (本身没有处理样式隔离、js执行隔离) ,实现了路由劫持和应用加载。

特点:

(1)在同一页面上使用多个框架而无需刷新页面

(2)独立部署

(3)使用新框架编写代码,无需重写现有应用程序

(4)延迟加载代码以改善初始加载时间

(5)本身没有处理样式隔离、js执行隔离,共用同一个window

single-spa官方文档:https://zh-hans.single-spa.js.org/

二、SystemJs

1、概念

SystemJs是一个通用的模块加载器,他能在浏览器和node环境上动态加载模块,微前端的核心就是加载子应用,因此将子应用打包成模块,在浏览器中通过SystemJs来加载模块。

缺点:版本兼容性差,对开发者体验不好

2、快速理解

System.js拆分成两部分,一部分是导入文件“systemjs-importmap”,这里和我们使用es导入一样需要声明对照关系,另一部分是注册模块

(1)在es的写法通常是这样 'import 变量 from 位置' 直接使用变量

(2)在'systemjs' 中是 System.import(),引入的包中会注册模块,System.register("注册变量名",function(){}),这里的模块需要在systemjs-importmap中声明,如果webpack.config.js中没有配置externals,这里就会注册一个空数组

代码语言:txt
AI代码解释
复制
<!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>
  </head>
  <body>
    <script type="systemjs-importmap">
      {
        "imports": {
          "react": "https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js",
          "react-dom": "https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"
        }
      }
    </script>
    <div id="root"></div>
    <script src="https://cdn.bootcdn.net/ajax/libs/systemjs/6.10.1/system.min.js"></script>
    <script>
      // 项目打包后,生成index.js,打包配置中将react和react-dom提取出来了
      // 依赖前置,引入index.js时
      // index.js里面会注册通过externals提取出的模块,ystem.register(["react","react-dom"], function(__WEBPACK_DYNAMIC_EXPORT__, __system_context__) {})
      // 因此需先加载react和react-dom
      System.import("./index.js");
    </script>
  </body>
</html>

项目打包后,输出system模块,并提取公共模块

代码语言:txt
AI代码解释
复制
const path = require("path");
module.exports = (env) => {
  return {
    mode: "development",
    output: {
      filename: "index.js",
      path: path.resolve(__dirname, "dist"),
      // 打包格式,system模块
      libraryTarget: env.production ? "system" : "",
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          use: {
            loader: "babel-loader",
          },
          exclude: /node_modules/,
        },
      ],
    },
    plugins: [
      !env.production &amp;&amp;
        new HtmlWebpackPlugin({
          template: "./public/index.html",
        }),
    ].filter(Boolean),
    externals: env.production ? ["react", "react-dom"] : [],
  };
};

3、在single-spa中的应用

在 single-spa的使用过程中,我们需要用importmap在根项目中引入所有的模块文件和子项目,从而在其余项目中可以进行模块的引用,我们开发者需要做的,就是把模块文件打包,然后通过 importmap引入,实现子模块的引入。

在使用single-spa时,不必使用SystemJS,不过为了能够独立部署各应用,很多示例和教程会推荐使用SystemJS。

代码语言:txt
AI代码解释
复制
<!-- 项目启动后,会去找对应端口下的文件 -->
  <script type="systemjs-importmap">
    {
      "imports": {
        "@single-spa/root-config": "//localhost:9000/single-spa-root-config.js",
        "@single-spa/vue-app": "//localhost:8080/js/app.js",
        "@single-spa/react-app": "//localhost:8081/single-spa-react-app.js"
      }
    }
  </script>

三、快速上手

1、single-spa脚手架

(1)全局下载create-single-spa

npm i create-single-spa -g

(2)创建项目

create-single-spa 应用名

创建项目的类型.jpg
创建项目的类型.jpg

这里会让选择类型,第一个中application就是应用,parcel不受路由控制,相当于公共组件,多个应用可以引入,实现组件的共享;第二个是公共的模块,主要是一些工具方法;第三个是基座应用;根据当前创建的类型选择即可。

(3)基座应用

生成的目录结构:

代码语言:txt
AI代码解释
复制
├─ src                      
│  ├─ index.ejs             
│  └─ *-root-config.js  
├─ package-lock.json        
├─ package.json             
└─ webpack.config.js

index.ejs,主要引入system.js,并在importmap中配置好公共模块地址和子应用地址,做到按需导入,通过System.import('')引入基座。

代码语言:txt
AI代码解释
复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Root Config</title>
  <!-- async/await 解析包-->
  <script src="https://cdn.jsdelivr.net/npm/regenerator-runtime@0.13.7/runtime.min.js"></script>
 
  <meta http-equiv="Content-Security-Policy" content="default-src 'self' https: localhost:*; script-src 'unsafe-inline' 'unsafe-eval' https: localhost:*; connect-src https: localhost:* ws://localhost:*; style-src 'unsafe-inline' https:; object-src 'none';">
  <meta name="importmap-type" content="systemjs-importmap" />
  
  <!-- 
    single-spa:帮助挂载应用、切换应用,
    react 和 react-dom打包时会自动抽取,react-router-dom需要单独在externals中抽取
   -->
  <script type="systemjs-importmap">
    {
      "imports": {
        "single-spa": "https://cdn.jsdelivr.net/npm/single-spa@5.9.0/lib/system/single-spa.min.js",
        "react":"https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js",
        "react-dom":"https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js",
        "react-router-dom":"https://cdn.bootcdn.net/ajax/libs/react-router-dom/5.2.0/react-router-dom.min.js"
      }
    }
  </script>
  <!-- 预加载 -->
  <link rel="preload" href="https://cdn.jsdelivr.net/npm/single-spa@5.9.0/lib/system/single-spa.min.js" as="script">

  <% if (isLocal) { %>
    <!-- 项目启动后,会去找对应端口下的文件 -->
  <script type="systemjs-importmap">
    {
      "imports": {
        "@single-spa/root-config": "//localhost:9000/single-spa-root-config.js",
        "@single-spa/vue-app": "//localhost:8080/js/app.js",
        "@single-spa/react-app": "//localhost:8081/single-spa-react-app.js"
      }
    }
  </script>
  <% } %>

  <script src="https://cdn.jsdelivr.net/npm/import-map-overrides@2.2.0/dist/import-map-overrides.js"></script>
  <!-- 本地加载未压缩的,否则加载压缩后的 -->
  <% if (isLocal) { %>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/system.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/extras/amd.js"></script>
  <% } else { %>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/system.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/extras/amd.min.js"></script>
  <% } %>
</head>
<body>
  <noscript>
    You need to enable JavaScript to run this app.
  </noscript>
  <main></main>
  <script>
    // 引入基座
    System.import('@single-spa/root-config');
  </script>
  <import-map-overrides-full show-when-local-storage="devtools" dev-libs></import-map-overrides-full>
</body>
</html>

*-root-config.js,主要配置文件,注册子应用,并启动

代码语言:txt
AI代码解释
复制
import { registerApplication, start } from "single-spa";

// 注册应用--默认的welcome
registerApplication({
  name: "@single-spa/welcome",  // 应用名
  app: () =>                    // 当路径匹配到时,执行该方法
    System.import(              // 加载了远程的模块,这个模块会暴露三个钩子函数
      "https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js"
    ),
  activeWhen: location => location.pathname === "/",// 激活时机
});

// 注册vue子应用
registerApplication({
  name: "@single-spa/vue-app",  // 应用名
  app: () =>                    // 当路径匹配到时,执行该方法
    System.import(              // 加载了在index.ejs中的importmap的"@single-spa/vue-app配置项
      "@single-spa/vue-app"
    ),
  activeWhen: ["/vue-app"],     // 以/vue-app开头的
  customProps: { app: 'vue' }  // 自定义传参
});

// 注册react子应用
registerApplication({
  name: "@single-spa/react-app",  // 应用名
  app: () =>                    // 当路径匹配到时,执行该方法
    System.import(              // 加载了在index.ejs中的importmap的@single-spa/react-app配置项
      "@single-spa/react-app"
    ),
  activeWhen: ["/react-app"],     // 以/react-app开头的
  customProps: { app: 'react' }  // 自定义传参
});

// 启动应用
start({
  urlRerouteOnly: true,  // 是否可以通过 history.pushState() 和 history.replaceState() 更改触发 single-spa 路由,默认false,不允许
});

webpack.config.js,webpack配置文件,这个文件主要导入了 "webpack-config-single-spa",一个可共享的、可定制的 webpack 配置,是已经帮忙做好的关于single-spa的webpack 文件。

代码语言:txt
AI代码解释
复制
const { merge } = require("webpack-merge");
const singleSpaDefaults = require("webpack-config-single-spa");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = (webpackConfigEnv, argv) => {
  // 在importmap中引入时为:@single-spa/root-config
  const orgName = "single-spa";  // 组织名
  const defaultConfig = singleSpaDefaults({  // @single-spa/root-config
    orgName,
    projectName: "root-config",   // 项目名
    webpackConfigEnv, 
    argv,
    disableHtmlGeneration: true,  // 因为下面配置了HtmlWebpackPlugin,所以为true,默认为false,禁用HtmlWebpackPlugin
  });

  return merge(defaultConfig, {
    // modify the webpack config however you'd like to by adding to this object
    plugins: [
      new HtmlWebpackPlugin({
        inject: false,
        template: "src/index.ejs",
        templateParameters: {
          isLocal: webpackConfigEnv &amp;&amp; webpackConfigEnv.isLocal,
          orgName,
        },
      }),
    ],
  });
};

(4)vue子应用

main.js中,导出三个钩子函数

代码语言:txt
AI代码解释
复制
import { h, createApp } from 'vue';
import singleSpaVue from 'single-spa-vue';

import App from './App.vue';

// 利用了vue-cli-single-spa-plugin插件改写
const vueLifecycles = singleSpaVue({
  createApp,
  appOptions: {
    render() {
      // 将接收到的参数传给了App组件
      return h(App, {
        app: this.app   
      });
    },
  },
});

// 导出三个钩子函数,让基座拿到
export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;

路由中,需要设置路由前缀,以便对应父应用中子应用的激活方式

代码语言:txt
AI代码解释
复制
import {createRouter, createWebHistory} from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue')
  }
]

const router = createRouter({
  // 路由前缀
  history: createWebHistory('/vue-app'),
  routes
})

export default router

可以在vue.config.js中修改运行端口

代码语言:txt
AI代码解释
复制
// 修改运行端口
module.exports = {
    devServer: {
        port: 8080
    }
}

(5)react子应用

入口js文件

代码语言:txt
AI代码解释
复制
import React from "react";
import ReactDOM from "react-dom";
import singleSpaReact from "single-spa-react";
import Root from "./root.component";

const lifecycles = singleSpaReact({
  React,                              // 主React对象
  ReactDOM,                           // 主ReactDOMbject
  rootComponent: Root,                // 将被渲染的顶层React组件
  errorBoundary(err, info, props) {   // 错误边界
    return null;
  },
});

// 导出三个钩子函数
export const { bootstrap, mount, unmount } = lifecycles;

在webpack.config.js中将react-router-dom手动抽取出来,react和react-dom会自动抽取

代码语言:txt
AI代码解释
复制
const { merge } = require("webpack-merge");
const singleSpaDefaults = require("webpack-config-single-spa-react");

module.exports = (webpackConfigEnv, argv) => {
  const defaultConfig = singleSpaDefaults({
    orgName: "single-spa",
    projectName: "react-app",
    webpackConfigEnv,
    argv,
  });

  // 合并singlespa和自定义的配置
  return merge(defaultConfig, {
    // 抽取react-router-dom
    externals: ['react-router-dom']
  });
};

package.json中修改启动端口

代码语言:txt
AI代码解释
复制
"scripts": {
    "start": "webpack serve --port 8081",
    "start:standalone": "webpack serve --env standalone",
    "build": "concurrently npm:build:*"
  },

由于子应用都是经过single-spa改造过的,因此运行起来有些不同

直接运行yarn start,会提示微前端不在这,需要到主应用的端口访问

yarn start.png
yarn start.png

yarn start:standalone,单独运行

yarn start:standalone.png
yarn start:standalone.png

2、手动配置

2.1 创建好基座应用和子应用

2.2 通过system接入子应用

(1)改造基座

下载single-spa

代码语言:txt
AI代码解释
复制
npm i single-spa

index.html,引入systemjs,importmap中配置上子应用地址

代码语言:txt
AI代码解释
复制
<!DOCTYPE html>
<html lang="">
  <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">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
    <meta name="importmap-type" content="systemjs-importmap" />
    <script type="systemjs-importmap">
      {
        "imports": {
          "child_vue":"http://localhost:8081/js/app.js"
        }
      }
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.1.1/system.min.js"></script>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
  </body>
</html>

main.js,注册子应用

代码语言:txt
AI代码解释
复制
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// registerApplication注册应用,start开启应用
import {registerApplication,start} from 'single-spa'

Vue.config.productionTip = false
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

// 注册vue项目
registerApplication(
  'child_vue',
  () => window.System.import('child_vue'),
  location => location.pathname.startsWith('/child_vue'),
  {
    appName:'child_vue啦啦'
  }
)

// 启动子应用
start()

(2)改造子应用

下载对应的包装器,如single-spa-vue,下载几个包:systemjs-webpack-interop、vue-cli-plugin-single-spa

代码语言:txt
AI代码解释
复制
npm i single-spa-vue systemjs-webpack-interop
npm i vue-cli-plugin-single-spa -D

router/index.js,跟前面一样的,添加路由前缀

main.js,引入single-spa-vue包装器,导出生命周期钩子函数

代码语言:txt
AI代码解释
复制
import './set-public-path';
import Vue from 'vue';
import singleSpaVue from 'single-spa-vue';

import App from './App.vue';
import router from './router';

Vue.config.productionTip = false;

const vueLifecycles = singleSpaVue({
  Vue,
  appOptions: {
    el:"#child_vue",  // 父组件中放子应用的标签
    router,
    render(h) {
      return h(App, {
        props: {
          // 基座应用传的值
          appName: this.appName
        },
      });
    },
  },
});

// 导出三个生命周期
export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;

set-public-path.js,引入systemjs-webpack-interop,它是一个npm包,它导出的函数可以帮你创建一个webpack包,这个包可以被systemjs作为浏览器内模块使用。调用setPublicPath设置公共路径。

代码语言:txt
AI代码解释
复制
import { setPublicPath } from 'systemjs-webpack-interop';

// setPublicPath(systemjsModuleName, rootDirectoryLevel = 1)设置公共路径
// systemjsModuleName:systemjs模块的字符串名称。这个名称应该存在于导入映射中。
// rootDirectoryLevel:默认为1的整数,表示将使用哪个目录作为公共路径。使用计算公共路径,1表示“当前目录”,2表示“向上一个目录”
setPublicPath('child_vue', 2);

vue.config.js,配置端口,打包成system模块

代码语言:txt
AI代码解释
复制
module.exports = {
  devServer: {
    port: 8081
  },
  chainWebpack: (config) => {
    config.devServer.set('inline', false);
    config.devServer.set('hot', true);
    if (process.env.NODE_ENV !== 'production') {
      config.output.filename(`js/[name].js`);
    }
    // 打包成system模块
    config.output.libraryTarget('system');
    config.externals(['vue', 'vue-router']);
  },
  filenameHashing: false,
};

2.3 通过umd接入子应用

(1)改造基座

下载single-spa

代码语言:txt
AI代码解释
复制
npm i single-spa

main.js,注册子应用,通过动态创建script标签已引入子应用文件,并启动应用

代码语言:txt
AI代码解释
复制
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// registerApplication注册应用,start开启应用
import {registerApplication,start} from 'single-spa'

Vue.config.productionTip = false

function loadUrl(url){
  return new Promise((resolve,reject) => {
    const el = document.createElement("script")
    el.src = url
    el.onload = resolve
    el.onerror = reject
    document.head.appendChild(el)
  })
}

// 注册子应用-vue
// registerApplication(要加载的组件的名字,要使用的方法且必须是个promise函数,什么时候加载组件默认有个location的参数,需要父子传的参数)
registerApplication("child_vue",async () => {
  // 要把子组件的包引进来,必须通过自定义标签,顺序必须如此
  await loadUrl("http://localhost:8081/js/chunk-vendors.js")
  await loadUrl("http://localhost:8081/js/app.js")
  return window.child_vue
},location => location.pathname.startsWith("/child_vue"),
{appName:'child_vue  umd包'}
)

// 启动子应用
start()

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

(2)改造子应用

router/index.js,如上面一样,添加路由前缀

main.js,注册子应用,导出生命周期钩子函数,接收主应用传来的参数

代码语言:txt
AI代码解释
复制
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import singleSpaVue from 'single-spa-vue'

Vue.config.productionTip = false

// 要被父应用加载,必须暴露三个接口 bootstrap mount unmount ,可以用协议直接生成
const vueLifecycles = singleSpaVue({
  Vue,
  appOptions: {
    el:"#child_vue",  // 父组件中放子应用的标签
    router,
    render(h) {
      return h(App, {
        props: {
          // 基座应用传的值
          appName: this.appName
        },
      });
    },
  },
});

// 若是父项目访问,则将路径定为子项目的路径
if(window.singleSpaNavigate){
  __webpack_public_path__ = "http://localhost:8081/"
}else{
  // 可以单独运行
  delete appOptions.el
  new Vue(appOptions).$mount("#app")
}
// 从singleSpa包装好的生命周期中导出接口
export const bootstrap = vueLifecycles.bootstrap
export const mount = vueLifecycles.mount
export const unmount = vueLifecycles.unmount

vue.config.js,配置应用打包出来的模块类型和应用运行端口号

代码语言:txt
AI代码解释
复制
module.exports = {
    configureWebpack:{
        output:{   // 打包成一个库
            library:"child_vue",
            // 打包完是一个umd模块,可以把导出的 bootstrap mount unmount 放到childApp里面,然后挂在window上
            libraryTarget:"umd"  
        },
        devServer:{
            port:8081
        }
    }
}

针对各个框架,single-spa提供了很多包装器,包装器可以把子应用进行包装,给子应用提供生命周期钩子,并将其导出。

四、最后

Single-spa 在一定程度上来说已经可以帮我们实现微前端了,但是实现的部分也很基础,还有很多问题需要解决。

比如改造老项目,大部分的老项目并没有打包成一个 js,并且接入微前端也不是一次性全部拆分,可能是先拆出去一部分。将已有模块拆分成子项目,需要将子项目打包成systemjs 能够导入的 js,这需要对项目配置做一定的改变,但是systemjs的兼容性也不好。引入项目以后,还需要考虑到子项目对其他模块的影响,虽然我们可以制定规范,比如各子项目使用唯一地命名前缀等,但这种人为约定往往又是不那么靠谱,对于css,我们还可以在构建时使用一些工具自动添加前缀,这样可以比较靠谱的避免冲突;对于js来说,比较靠谱的方式可能就是人为制造沙箱,让子应用的js都运行在各自的沙箱中,但这实现起来相对就比较复杂了。

总的来说 single-spa 是一个非常基础的微前端框架,应用引入麻烦,很多微前端该有的功能他都没有,因此,在single-spa的基础上诞生了qiankun,开箱即用、接入简单,更适合真正的运用在项目中。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
使用Matplotlib对数据进行高级可视化(基本图,3D图和小部件)
可视化在当今世界许多领域的结果传播中发挥着重要作用。如果没有适当的可视化,很难揭示结果,理解变量之间的复杂关系并描述数据的趋势。
代码医生工作室
2019/06/21
4K0
使用Matplotlib对数据进行高级可视化(基本图,3D图和小部件)
深度好文 | Matplotlib 可视化最有价值的 50 个图表(附完整 Python 源代码)
在数据分析和可视化中最有用的 50 个 Matplotlib 图表。 这些图表列表允许您使用 python 的 matplotlib 和 seaborn 库选择要显示的可视化对象。
数据派THU
2019/05/09
1.8K0
深度好文 | Matplotlib 可视化最有价值的 50 个图表(附完整 Python 源代码)
深度学习基础之matplotlib,一文搞定各个示例
Matplotlib 是 Python 的绘图库。它可与 NumPy 一起使用 ,Matplotlib也是深度学习的常用绘图库,主要是将训练的成果进行图形化,因为这样更直观,更方便发现训练中的问题,今天来学习下,走起!!
香菜聊游戏
2021/10/19
1.7K0
深度学习基础之matplotlib,一文搞定各个示例
Python数据分析之matplotlib(应用篇)
matplotlib核心剖析(http://www.cnblogs.com/vamei/archive/2013/01/30/2879700.html#commentform)
AI异构
2020/07/29
3590
Python数据分析之matplotlib(应用篇)
绘图技巧 | 我总结了雷达图的绘制方法(R+Python)
今天给大家介绍的的图表为雷达图(Radar/Spider chart),这种类型图表在生活中较常使用,是一种以从同一点开始的轴上表示的三个或更多个定量变量的二维图表的形式显示多变量数据的图形方法。较常用的场景多为分析企业经营状况(收益性、生产性、流动性、安全性和成长性)。本期推文带你使R-Python绘制雷达图,主要内容如下:
DataCharm
2021/04/16
6.1K0
绘图技巧 | 我总结了雷达图的绘制方法(R+Python)
25 个常用 Matplotlib 图的 Python 代码,收藏收藏!
大家好,今天要分享给大家25个Matplotlib图的汇总,在数据分析和可视化中非常有用,文章较长,可以马起来慢慢练手。
Python数据科学
2020/05/26
8680
python matplotlib各种绘图类型完整总结
plot([x], y, [fmt], [x2], y2, [fmt2], …, **kwargs)
Twcat_tree
2022/12/05
6.2K0
python matplotlib各种绘图类型完整总结
数据分析最有用的Top 50 Matplotlib图(带有完整的Python代码)(上)
50个Matplotlib图的汇编,在数据分析和可视化中最有用。此列表允许您使用Python的Matplotlib和Seaborn库选择要显示的可视化对象。
Datawhale
2019/10/18
2.1K0
数据分析最有用的Top 50 Matplotlib图(带有完整的Python代码)(上)
利用Python绘制全国各省新型冠状病毒疫情变化动态图
题图:Image by enriquelopezgarre from Pixabay
猴哥yuri
2020/02/25
2.6K0
又再肝3天,整理了65个Matplotlib案例,这能不收藏?
Matplotlib 作为 Python 家族当中最为著名的画图工具,基本的操作还是要掌握的,今天就来分享一波
周萝卜
2021/11/08
2.6K0
matplotlib 3D 绘图(二)
四. 3D 散点图 from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np
用户6021899
2019/08/14
8290
Matplotlib 可视化最有价值的 14 个图表(附完整 Python 源代码)
这些图表根据可视化目标的7个不同情景进行分组。 例如,如果要想象两个变量之间的关系,请查看“关联”部分下的图表。 或者,如果您想要显示值如何随时间变化,请查看“变化”部分,依此类推。
CSDN技术头条
2019/11/19
1.2K0
Matplotlib 可视化最有价值的 14 个图表(附完整 Python 源代码)
Matplotlib 1.4W+字基础教程来了(收藏吃灰去吧~~)
参考:Rougier N P, Droettboom M, Bourne P E, et al. Ten Simple Rules for Better Figures[J]. PLOS Computational Biology【IF 4.7】, 2014, 10(9).感兴趣戳:https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4161295/pdf/pcbi.1003833.pdf
DataCharm
2021/02/22
1.6K0
Matplotlib 1.4W+字基础教程来了(收藏吃灰去吧~~)
Python matplotlib绘制雷达图
雷达图也被称为网络图,蜘蛛图,星图,蜘蛛网图,是一个不规则的多边形。雷达图可以形象地展示相同事物的多维指标,应用场景非常多。
Python碎片公众号
2021/02/26
3.2K0
Python matplotlib绘制雷达图
matplotlib进阶:Artist
FigureCanvas 和 Renderer 解决和用户界面(如 wxPython)或绘图语言(如 PostScript)间通信的所有细节。而Artists 解决figure,text,lines这些元素的呈现和布局相关的所有细节。通常95%的时间都会花在 Artists 上。
bugsuse
2020/04/21
1.6K0
matplotlib进阶:Artist
python下Matplotlib绘图案例与常见设置简介
首先一幅Matplotlib的图像组成部分介绍。 基本构成 在matplotlib中,整个图像为一个Figure对象。在Figure对象中可以包含一个或者多个Axes对象。每个Axes(ax)对象都是
学到老
2018/04/17
1.6K0
python下Matplotlib绘图案例与常见设置简介
matplotlib安装及使用
matplotlib是基于python语言的开源项目,旨在为python提供一个数据绘图包。我将在这篇文章中介绍matplotlib API的核心对象,并介绍如何使用这些对象来实现绘图。实际上,matplotlib的对象体系严谨而有趣,为使用者提供了巨大的发挥空间。用户在熟悉了核心对象之后,可以轻易的定制图像。matplotlib的对象体系也是计算机图形学的一个优秀范例。即使你不是python程序员,你也可以从文中了解一些通用的图形绘制原则。matplotlib使用numpy进行数组运算,并调用一系列其他的python库来实现硬件交互。matplotlib的核心是一套由对象构成的绘图API。
狼啸风云
2023/10/07
6490
matplotlib安装及使用
Matplotlib从入门到精通02-层次元素和容器
参考: https://datawhalechina.github.io/fantastic-matplotlib/%E7%AC%AC%E4%B8%80%E5%9B%9E%EF%BC%9AMatplotlib%E5%88%9D%E7%9B%B8%E8%AF%86/index.html
IT从业者张某某
2023/10/16
6370
Matplotlib从入门到精通02-层次元素和容器
Matplotlib_Study01
from matplotlib.font_manager import FontProperties
Echo_Wish
2023/11/30
3050
Matplotlib_Study01
推荐阅读
相关推荐
使用Matplotlib对数据进行高级可视化(基本图,3D图和小部件)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档