sveltejs结合ol实现跨框架组件复用

Posted 牛老师讲GIS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sveltejs结合ol实现跨框架组件复用相关的知识,希望对你有一定的参考价值。

概述

velte 是构建 Web 应用程序的一种新方法,核心思想在于通过静态编译减少框架运行时的代码量,它可以像React和VUE一样开发,但却没有虚拟DOM,可以将代码编译为体积小、不依赖于框架的JS代码。使用Svelte开发的无框架依赖的Web Components,可以在各个框架间复用。同时,Svelte的开发方式也不像写pure js那样繁琐。本文将结合ol实现跨框架组件复用。

实现

1. 创建工程

创建Svelte template工程。 svelte 官方提供了template 工程(https://github.com/sveltejs/component-template),只要clone或者下载项目即可。

2. 添加依赖

修改package.json文件,修改后执行命令npm i安装依赖。修改后的文件内容为:


  "name": "svelte-component",
  "svelte": "src/index.js",
  "module.prod": "dist/index.min.mjs",
  "main.prod": "dist/index.min.js",
  "module.dev": "dist/index.mjs",
  "main.dev": "dist/index.js",
  "scripts": 
    "dev": "rollup -wc ./config/rollup.config.dev.js",
    "build": "rollup -c ./config/rollup.config.js",
    "prepublishOnly": "npm run build",
    "tree": "treee -I \\"node_modules\\""
  ,
  "devDependencies": 
    "@babel/core": "^7.20.12",
    "@babel/preset-env": "^7.20.2",
    "@rollup/plugin-node-resolve": "^15.0.1",
    "autoprefixer": "^10.4.13",
    "node-sass": "^8.0.0",
    "postcss": "^8.4.21",
    "rollup": "^2.0.0",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-svelte": "^7.0.0",
    "rollup-plugin-uglify": "^6.0.4",
    "rollup-obfuscator": "^3.0.1",
    "rollup-plugin-livereload": "^2.0.5",
    "rollup-plugin-serve": "^1.1.0",
    "sass": "^1.57.1",
    "svelte": "^3.5.0",
    "svelte-preprocess": "^5.0.1"
  ,
  "keywords": [
    "svelte"
  ],
  "files": [
    "src",
    "dist"
  ],
  "dependencies": 
    "ol": "^7.2.2"
  

3. 调整目录组织,添加配置

调整目录组织,调整后的目录组织如下:

sveltejs-component-template
├── README.md 
├── config
│   ├── rollup.config.dev.js  // 开发配置文件
│   └── rollup.config.js  // 编译配置文件
├── dist //  编译及调试文件
│   ├── index.html  // 调试文件
│   ├── index.js
│   ├── index.min.js
│   ├── index.min.mjs
│   └── index.mjs
├── package.json
└── src
    ├── ComponentMap.svelte
    └── index.js

rollup.config.dev.js文件内容如下:

import svelte from 'rollup-plugin-svelte'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
import sveltePreprocess from 'svelte-preprocess';
import serve from 'rollup-plugin-serve'
import livereload from 'rollup-plugin-livereload'
import pkg from '../package.json';

const name = pkg.name
  .replace(/^(@\\S+\\/)?(svelte-)?(\\S+)/, '$3')
  .replace(/^\\w/, m => m.toUpperCase())
  .replace(/-\\w/g, m => m[1].toUpperCase());

const preprocess = sveltePreprocess(
  scss: 
    includePaths: ['src'],
  ,
  postcss: 
    plugins: [require('autoprefixer')],
  ,
);

export default 
  input: 'src/index.js',
  output: [
     file: pkg['module.dev'], 'format': 'es' ,
     file: pkg['main.dev'], 'format': 'umd', name, sourcemap: false 
  ],
  plugins: [
    serve(
      contentBase: 'dist', // 服务器启动的文件夹,默认是项目根目录
      port: 18080 // 端口号
    ),
    livereload('dist'), // 监听dist目录
    babel(
      babelrc: false,
      exclude: "node_modules/**",
      presets: [
        [
          '@babel/preset-env',
          
            loose: true,
            // No need for babel to resolve modules
            modules: false,
            targets: 
              // ! Very important. Target es6+
              esmodules: true,
            ,
          ,
        ],
      ]
    ),
    svelte(
      preprocess: preprocess,
      compilerOptions: 
        customElement: true
      
    ),
    //(resolve要放在commonjs之前)
    resolve(),
    commonjs(
      include: 'node_modules/**'
    )
  ],
;

rollup.config.js文件内容如下:

import svelte from 'rollup-plugin-svelte'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
import  uglify  from 'rollup-plugin-uglify'
import  obfuscator  from 'rollup-obfuscator';
import sveltePreprocess from 'svelte-preprocess';
import pkg from '../package.json';

const name = pkg.name
  .replace(/^(@\\S+\\/)?(svelte-)?(\\S+)/, '$3')
  .replace(/^\\w/, m => m.toUpperCase())
  .replace(/-\\w/g, m => m[1].toUpperCase());

const preprocess = sveltePreprocess(
  scss: 
    includePaths: ['src'],
  ,
  postcss: 
    plugins: [require('autoprefixer')],
  ,
);

export default 
  input: 'src/index.js',
  output: [
     file: pkg['module.prod'], 'format': 'es' ,
     file: pkg['main.prod'], 'format': 'umd', name, sourcemap: false 
  ],
  plugins: [
    babel(
      babelrc: false,
      exclude: "node_modules/**",
      presets: [
        [
          '@babel/preset-env',
          
            loose: true,
            // No need for babel to resolve modules
            modules: false,
            targets: 
              // ! Very important. Target es6+
              esmodules: true,
            ,
          ,
        ],
      ]
    ),
    svelte(
      preprocess: preprocess,
      compilerOptions: 
        customElement: true
      
    ),
    //(resolve要放在commonjs之前)
    resolve(),
    commonjs(
      include: 'node_modules/**'
    ),
    obfuscator(),
    uglify()
  ],
;

4. 组件编写

ComponentMap.svelte文件的内容如下:

<svelte:options tag="ol-map" />

<div bind:this=mapDom class="map">
</div>

<script>
    import  createEventDispatcher, onMount  from 'svelte';
    import Map from 'ol/Map.js'
    import XYZSource from 'ol/source/XYZ.js'
    import TileLayer from 'ol/layer/Tile.js'
    import View from 'ol/View.js'
    import  fromLonLat  from 'ol/proj'

    export let center = '0,0';

    let map = null
    let mapDom;

    // 监听变化
    $: valueChanged(center);
    function valueChanged(newValue) 
        if(map)
            map.setCenter(getCenter(newValue))
        
    

    // 事件
    const dispatch = createEventDispatcher();
    function dispatchEvent(name, e) 
        // dispatch(name, e);
        const event = new CustomEvent(name, 
            detail: e,
            bubbles: true,
            cancelable: true,
            composed: true
        );
        mapDom.dispatchEvent(event);
    

    function getCenter(center) 
        return center.split(',').map(Number)
    
    // 生命周期函数
    onMount(() => 
        map = new Map(
            target: mapDom,
            layers: [
                new TileLayer(
                    source: new XYZSource(
                        url: 'https://gac-geo.googlecnapps.cn/maps/vt?lyrs=m&x=x&y=y&z=z'
                    )
                )
            ],
            view: new View(
                center: fromLonLat(getCenter(center)),
                zoom: 4
            )
        );
        map.on('zoomend', e => 
            dispatchEvent("zoomend", map.getZoom());
        );
    );
</script>

<style lang="scss">
  .map 
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
  
</style>

index.js文件的内容如下:

export  default as default  from './ComponentMap.svelte';

5. 打包编译

执行命令npm run devnpm run build进行开发调试和编译打包。其中index.html为开发时调试文件,其内容为:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
  <script src="./index.js"></script>
  <style>
    html, body 
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
    
    .map 
      /*height: 500px;*/
      /*width: 500px;*/
      height: 100%;
      width: 100%;
    
  </style>
</head>
<body>
<div class="map">
  <ol-map center="113.940159,22.524729"></ol-map>
</div>
<script>
  const olMap = document.querySelector("ol-map")
  olMap.addEventListener("mapload", e => 
    console.log(e.detail)
  )
  olMap.addEventListener("zoomend", e => 
    console.log(e.detail)
  )
</script>
</body>
</html>

运行后效果如:

完整代码请移步:https://gitee.com/lzugis15/sveltejs-component-template.git

以上是关于sveltejs结合ol实现跨框架组件复用的主要内容,如果未能解决你的问题,请参考以下文章

Svelte入门——Web Components实现跨框架组件复用

Svelte入门——Web Components实现跨框架组件复用

Svelte入门——Web Components实现跨框架组件复用

Svelte入门——Web Components实现跨框架组件复用

Svelte入门——Web Components实现跨框架组件复用

美团民宿跨端复用框架设计与实践