# 支持商城自定义开发——NPM包方式引入

### 方案说明
> 商城端将需要自定义的部分封装成npm组件，流桌面端在项目中引用进来即可。说明：商城端主要负责样式部分，及部分接口逻辑部分。而按键的触发则是商城部分通过告诉流桌面端自己按下了哪个按键，然后流桌面端进行触发。考虑安全性，可以将npm私有化部署。考虑前端性能部分，减小发布到npm包的体积与避免重复依赖。

### 验证说明
> 已将菜单、虚拟键盘以npm组件的形式导出，然后流桌面端引入，放在正式线上上线后，发现能达到商城自定义开发的目的。
  将云电脑组件发布成CDN的形式，供流桌面引入使用。

### 使用说明
1、各端尽可能使用统一的适配方法。比如我将流桌面端和云电脑自定义部分都统一使用postcss-px2rem-exclude和手淘的lib-flexible进行rem适配。使用postcss-px2rem-exclude，它的exclude方法可以排除改变node_modules下的第三方库的样式也改变。
```javascript
      // postcss-px2rem-exclude源码改造，不然exclude的参数会被当作字符串处理
      try {
      let flag = options.exclude.includes('/')
      if (flag) {
        let arr = options.exclude.split('/')
        options.exclude = new RegExp(arr[1], arr[2])
      }
    } catch (err) {
    }

    // lib-flexible源码改造，适配旋转屏幕以及ipad，refreshRem方法修改
    function refreshRem(){
        var width = document.documentElement.clientWidth
        var height = document.documentElement.clientHeight
        var ua = navigator.userAgent.toLowerCase()
        if (ua.match(/iPad/i) == 'ipad') {
            if (width / dpr > 1024) {
                if (width / dpr > 2048) {
                    width = 2048 * dpr
                } else {
                    width = 1024 * dpr
                }
            }
            if (height / dpr > 1024) {
                if (height / dpr > 2048) {
                    height = 2048 * dpr
                } else {
                    height = 1024 * dpr
                }
            }
        } else {
            if (width / dpr > 540) {
                width = 540 * dpr;
            }
            if (height / dpr > 540) {
                height = 540 * dpr
            }
        }
        var rem = width > height ? width / 10 : height / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }
```

2、因为npm包引入不支持商城端路由状态管理，商城自定义部分将需要全部导出的部分当成是一个大的组件，里面包含了各个小的组件。页面跳转可以通过组件正常通信的形式交互。
``` javascript
    <!-- 菜单栏组件 -->
    <slidebar-item
      :isSidwbar="isSidwbar"
      :screen="screenInfomation"
      :showFullScreenSwitch="showFullScreenSwitch"
      :firstLoad="firstLoad"
      @showKey="showKey"
      @away="away"
      @reset="reset"
      @goRechargeUrl="goRechargeUrl"
      @changemousespeed="changemousespeed"
      @createClick="createClick"
      @changeNet="changeNet"
      @showSidebar="showSidebar"
      @showFullScreen="showFullScreen"
      @sendDataBuriedPoint="sendDataBuriedPoint"
    >
    </slidebar-item>

    <!-- 网络监测组件 -->
    <network-item
      :isNetshow="isNetshow"
      :roundTripTime="roundTripTime"
      :byteRateSpeed="byteRateSpeed"
      :packetRate="packetRate"
      @closeNetWork="changeNet"
    >
    </network-item>

    <!-- 文字键盘组件 -->
    <textKeyboard
      :panel="panel"
      :allKey="allKey"
      :signKey="signKey"
      :SpeKey="SpeKey"
      :colorA="colorA"
      :colorB="colorB"
      :activeClass="activeClass"
      :allKeys="allKeys"
      :CapsallKeys="CapsallKeys"
      :numKey="numKey"
      :signKeys="signKeys"
      :speCtrls="speCtrls"
      @whickKeyTextKeyboard="whickKeyTextKeyboard"
      @KeyEndTextKeyboard="KeyEndTextKeyboard"
      @keySignDownTextKeyboard="keySignDownTextKeyboard"
      @keySpecailUp="keySpecailUp"
    >
    </textKeyboard>

    <!-- 自定义键盘组件 -->
    <customize-item
      :screen="screenInfomation"
      :universal="universal"
      :Showcustomize="Showcustomize"
      :customize_editBtn_data="customize_editBtn_data"
      :isHorizontalScreen="isHorizontalScreen"
      :popupNav="popupNav"
      :exitCustomEdit="exitCustomEdit"
      @initCustomizeShow="initCustomizeShow"
      @Showcustomize_son="Showcustomize_son"
      @clk_cus_close_sidebar="clk_cus_close_sidebar"
      @showNavBar="emitShowNavBar"
      @sendDataBuriedPoint="sendDataBuriedPoint"
    >
    </customize-item>
    <dragBox-item
      v-for="(item, index) in itemList"
      :key="index"
      :keymsg="item"
      :title="index"
      :screen="screenInfomation"
      :isHorizontalScreen="isHorizontalScreen"
      :dragBoxShowSidebar="dragBoxShowSidebar"
      :secondMenu="secondMenu"
      @transferData="transferData"
      @returnData="returnData"
      @updateElement="updateElement"
    >
    </dragBox-item>

    <div v-show="show_customize_div">
      <div style="display:flex;">
        <div class="exitBtn_cus editBtn" ref="exitBtn_cus" @click="cus_editFn">编辑</div>
        <div class="exitBtn_cus" ref="exitBtn_cus" @touchstart="cus_exitFn">退出</div>
      </div>
    </div>

    <!-- 官方虚拟键盘组件 -->
    <officialKeyboard
      :officialKeyboardFlag="officialKeyboardFlag"
      :screen="screenInfomation"
      @exitOfficialKeyboard="exitKey"
      @transferData="transferData"
      @returnData="returnData"
    ></officialKeyboard>
```

3、 流桌面端引入商城自定义npm包，传给商城需要的数据以及处理商城按下的虚拟按键发送给服务器的命令。以及在商城各个线上及修改之后更新npm包的版本号，可以使用npm link解决多模块依赖或者遍历submodule的方式解决。

```javascript
        <customDevelopment
          :isSidwbar="isSidwbar"
          :showFullScreenSwitch="showFullScreenSwitch"
          :firstLoad="firstLoad"
          :roundTripTime="roundTripTime"
          :byteRateSpeed="byteRateSpeed"
          :packetRate="packetRate"
          :colorA="colorA"
          :colorB="colorB"
          :universal="universal"
          :dragBoxShowSidebar="isSidwbar"
          @changeSideBarShow="changeSideBarShow"
          @away="away"
          @reset="reset"
          @goRechargeUrl="goRechargeUrl"
          @changemousespeed="changemousespeed"
          @showSidebar="showSidebar"
          @showFullScreen="showFullScreen"
          @whickKeyTextKeyboard="whichKey"
          @KeyEndTextKeyboard="KeyEnd"
          @keySignDownTextKeyboard="keySignDown"
          @keySpecailUp="keySpecailUp"
          @transferData="transferData"
          @returnData="returnData"
          @clk_cus_close_sidebar="clk_cus_close_sidebar"
          @sendDataBuriedPoint="sendDataBuriedPoint"
        >
        </customDevelopment>
```

>相关参数解析:<br>
**props**<br>
isSidwbar  自定义菜单的显示与隐藏<br>
showFullScreenSwitch 是否显示全屏显示<br>
firstLoad 判断是否首次进入<br>
roundTripTime 延迟<br>
byteRateSpeed  网络<br>
packetRate  丢包<br>
colorA colorB  文字键盘中英文输入法状态切换的颜色改变<br>
**emit**<br>
changeSideBarShow、showSidebar、clk_cus_close_sidebar 控制菜单显示与隐藏<br>
away 暂时离开<br>
reset 游戏恢复<br>
goRechargeUrl 充值入口<br>
changemousespeed 改变鼠标速度<br>
showFullScreen  全屏显示方法<br>
whickKeyTextKeyboard、KeyEndTextKeyboard、keySignDownTextKeyboard、keySpecailUp  文字键盘的数据发送<br>
transferData、returnData  虚拟按键的数据发送<br>
sendDataBuriedPoint 发送埋点数据<br>

