首页 > 网站 > 帮助中心 > 正文

vue远程加载sfc组件思路详解

2024-07-09 22:42:50
字体:
来源:转载
供稿:网友

问题

在我们的 vue 项目中(特别是后台系统),总会出现一些需要多业务线共同开发同一个项目的场景,如果各业务团队向项目中提供一些公共业务组件,但是这些组件并不能和项目一起打包,因为项目中不能因为某个私有模块的频繁变更而重复构建发布。

^_^不建议在生产环境使用,代码包含eval 

思路

在这种场景下我们需要将公共的业务组件部署到服务端,由客户端请求并渲染组件。

服务端解析.vue文件

使用vue-template-compiler 模板解析器,解析SFC(单文件组件)

const compile = require('vue-template-compiler')// 获取sfc组件的源码const str = fs.readFileSync(path.resolve(__dirname, `../components/sfc.vue`), 'utf-8')// vue-loader内置,现在用来解析SFC(单文件组件)let sfc = compile.parseComponent(str)// 获取sfc组件配置let sfcOptions = getComponentOption(sfc)

getComponentOption 获取sfc组件配置

import { uuid } from 'utilscore'import stylus from 'stylus'import sass from 'sass'import less from 'less'const getComponentOption = sfc => {  // 生成data-u-id   const componentId = uuid(8, 16).toLocaleLowerCase()    // 标签添加data-u-id属性    const template = sfc.template ? tagToUuid(sfc.template.content, componentId) : ''    // 转化style(less、sass、stylus)    let styles = []    sfc.styles.forEach(sty => {        switch (sty.lang) {            case 'stylus':                stylus.render(sty.content, (err, css) => styles.push(formatStyl(sty, css, componentId)))                break;            case 'sass':            case 'scss':                styles.push(formatStyl(sty, sass.renderSync({ data: sty.content }).css.toString(), componentId))                break;            case 'less':                less.render(sty.content, (err, css) => styles.push(formatStyl(sty, css, componentId)))                break;        }    })    let options = {        script: sfc.script ? $require(null, sfc.script.content) : {},        styles,        template    }    return JSON.stringify(options, (k, v) => {    if(typeof(v) === 'function') {      let _fn = v.toString()      return /^function()/.test(_fn) ? _fn : fn.replace(/^/,'function ')    }    return v  })}

tagToUuid  给template 中的标签追加data-u-id 

const tagToUuid = (tpl, id) => {    var pattern = /<[^//]("[^"]*"|'[^']*'|[^'">])*>/g    return tpl.replace(pattern, $1 => {        return $1.replace(/<([/w/-]+)/i, ($2, $3) => `<${$3} data-u-${id}`)    })}

formatStyl 处理样式的scoped

const formatStyl = (sty, css, componentId) => {    let cssText = css    if (sty.scoped) {        cssText = css.replace(/[/./w/>/s]+{/g, $1 => {          if (/>>>/.test($1)) return $1.replace(//s+>>>/, `[data-u-${componentId}]`)          return $1.replace(//s+{/g, $2 => `[data-u-${componentId}]${$2}`)        })    }    return cssText}

$require 执行其中的的 JavaScript 代码,并返回值

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表