嗨大家好,想跟大家说说一个挺有趣的话题。你们有试过在 Vue 项目里,特别是后端那些系统,经常得让多个业务团队共同弄一个大项目是?说起来,有时候各个团队会把公用的小部件给这个项目用,但问题就来了,这些东西不能直接跟项目打包到一起,毕竟项目升级总是得多做几次的,要不因为某个私有的小部分改来改去每次都整个项目都更新太浪费时间了。遇到这样的问题怎么办?我这儿有些高招,快来听!
,先得把公用的业务组件上到服务器上,然后客户端在需要的时候会去请求和渲染它们。可是,要怎么从服务器那里解析.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)
接着,你得把data-u-id加到模板里的标签上。这主要是为了搞定样式那个“只会在自己家生效”的 scoped功能,防止跟其他组件的样式冲突~挺实用的,对!
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 }) }
接下来咱们这就要搞客户端请求,还要渲染那个啥组件来着。得先整一个叫remote.vue的前端远程组件,这个东西能帮我们弄好远程组件的事儿。其实,远程组件还是挺实用的!用了之后你就能在服役期内的sfc组件里添加JavaScript块了,记得要用module.exports导出来还有就是引用脚本时要用$require,这样就能把里面的JavaScript代码顺利运行起来并得到结果~
const tagToUuid = (tpl, id) => { var pattern = /])*>/g return tpl.replace(pattern, $1 => { return $1.replace(/ `<${$3} data-u-${id}`) }) }
最后一句话了,客户端渲染真的很关键!用刚才说的方法,就能让客户端自己申请组件还能渲染出来。这下子,公共业务组件用起来可多方便
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 }
告诉你们一个好消息!只要把公用的程序组件安装在服务器上,再用vue-template-compiler来解读模板,搞点data-u-id之类的东西,搞定scoped样式,封装一些神奇的前端元素比如’remote.vue’,最后在客户端渲染一下,就能解决好几个团队同时开发同一个项目的大难题。这个招数真的很厉害!相信能帮到大家不少忙,谢谢大家的关心!今天就聊到这儿!希望大家都喜欢我的话题。如果还有啥疑问或想法,欢迎随时留言讨论,还请各位不要吝惜点赞和分享给更多的人哟~下次再见咯!
const $require = (filepath, scriptContext) => { const filename = path.resolve(__dirname, `../${filepath}`); const module = { exports: {} } let code = scriptContext ? scriptContext : fs.readFileSync(filename, 'utf-8') let exports = module.exports code = `(function($require,module,exports,__dirname,filename){$})($require,module,exports,__dirname,filename)` eval(code) return module.exports }
评论0