zoukankan      html  css  js  c++  java
  • webpack学习:uni运行时代码解读一 (页面初始化加载)

    uni的vue代码是如何在微信小程序里面执行的,对此比较感兴趣所以去调试学习了一波.

    准备工作

    // 在vue.config.js里打开非压缩的代码
    module.exports = {
      configureWebpack: config => {
        config.devtool = 'none'
        config.mode = 'development'
      }
    }
    // 运行时代码路径  node_modules\@dcloudio\uni-mp-weixin\dist\index.js
    // uni修改过后的vue代码路径  node_modules\@dcloudio\vue-cli-plugin-uni\packages\mp-vue\dist\mp.runtime.esm.js
    
    

    页面初始化

    不管是页面还是组件,uni都是通过微信提供的全局component方法来实现的,uni在原生的conponent基础上做了一层代理

    const MPPage = Page;
    const MPComponent = Component;
    
    if (!MPPage.__$wrappered) {
      MPPage.__$wrappered = true;
      // page 也做了代理,但是没有使用(至少正常配置没有使用)
      Page = function (options = {}) {
        initHook('onLoad', options);
        return MPPage(options)
      };
      Page.after = MPPage.after;
    
      Component = function (options = {}) {
        initHook('created', options);
        return MPComponent(options)
      };
    }
    

    对外暴露了createComponent, createPage 这2个方法,在生成的vue文件里会调用这2个方法,这2个方法的核心都是parseComponent

    function createPage (vuePageOptions) {
      {
        // Component 是被包裹一次的wx原生方法
        return Component(parsePage(vuePageOptions))
      }
    }
    function parsePage (vuePageOptions) {
      return parseBasePage(vuePageOptions, {
        isPage,
        initRelation
      })
    }
    function createComponent (vueOptions) {
      {
        return Component(parseComponent(vueOptions))
      }
    }
    function parseBasePage (vuePageOptions, {
      isPage,
      initRelation
    }) {
      const pageOptions = parseComponent(vuePageOptions);
    
      initHooks(pageOptions.methods, hooks$1, vuePageOptions);
    
      pageOptions.methods.onLoad = function (query) {
        this.options = query;
        const copyQuery = Object.assign({}, query);
        delete copyQuery.__id__;
        this.$page = {
          fullPath: '/' + (this.route || this.is) + stringifyQuery(copyQuery)
        };
        this.$vm.$mp.query = query; // 兼容 mpvue
        this.$vm.__call_hook('onLoad', query);
      };
    
      return pageOptions
    }
    

    parseComponent的parseBaseComponent方法是把vue配置初始化为微信的配置文件(上面的代码贴出来不看都无所谓这里才真正的开始),把你vue的配置转换为微信小程序的配置

    function parseComponent (vueComponentOptions) {
      return parseBaseComponent(vueComponentOptions, {
        isPage,
        initRelation
      })
    }
    function parseBaseComponent (vueComponentOptions, {
        isPage,
        initRelation
      } = {}) {
          // Vue.extend(vueComponentOptions); 核心就是通过vue的extend方法生成一个构造器
        const [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions);
      
        const options = {
          multipleSlots: true,
          addGlobalClass: true,
          ...(vueOptions.options || {})
        };
        // 这个option就是微信用来生成组件的option
        const componentOptions = {
          options,
          // vue的data和methods都会合并然后放在wx的data里
          data: initData(vueOptions, Vue.prototype),
          // vue的mixins extends behaviors都合并然后变成wx的behaviors
          behaviors: initBehaviors(vueOptions, initBehavior),
          // vue的props转换而成
          properties: initProperties(vueOptions.props, false, vueOptions.__file),
          lifetimes: {
            attached () {
                // 获取到微信实例的props
              const properties = this.properties;
      
              const options = {
                mpType: isPage.call(this) ? 'page' : 'component',
                mpInstance: this,
                propsData: properties
              };
      
              // 初始化 vue 实例
              this.$vm = new VueComponent(options);
    
              // 执行vue实例的mount,这一步很特别,vue实例其实是没有任何的render,因为vue的template
              // 已经在打包的过程中变成wxml,给wx实例使用了,所以这个vue的实例的页面内容其实是空的,
              // 那如何处理vue的渲染watch呢,uni对vue的源码做了处理,在patch的时候,新建了一个空对象
              // 然后把data和computed里面的所有属性都复制给了新对象,从而达到了渲染watch的监听效果
              // 也就是说在uni里面的vue,所有的data和computed都是在渲染watch里面使用了的,可能对排除
              // 某些问题有所帮助
              this.$vm.$mount();
            },
            ready () {
              // 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
              // https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
              if (this.$vm) {
                this.$vm._isMounted = true;
                // 在微信实例的ready钩子里 触发vue的挂载钩子
                this.$vm.__call_hook('mounted');
                this.$vm.__call_hook('onReady');
              }
            },
            detached () {
              this.$vm && this.$vm.$destroy();
            }
          },
          pageLifetimes: {
            show (args) {
              this.$vm && this.$vm.__call_hook('onPageShow', args);
            },
            hide () {
              this.$vm && this.$vm.__call_hook('onPageHide');
            },
            resize (size) {
              this.$vm && this.$vm.__call_hook('onPageResize', size);
            }
          },
          methods: {
            __l: handleLink,
            __e: handleEvent
          }
        };
      
      
        if (isPage) {
          return componentOptions
        }
        return [componentOptions, VueComponent]
      }
      
    

    用一张图来快速理解

    uni的和vue的区别

    一 computed是立即执行,且所有data和computed都会成为渲染依赖
    二 vue的组件其实是没有任何页面的,页面都是微信组件的
    三 wx的实例是通过微信的component来生成的,不是page方法

  • 相关阅读:
    Window下安装Python
    使用Docker构建一个简单的nginx网页镜像
    solr通过界面管理删除索引和重建索引
    solr8.6添加中文分词器
    php使用solr基础代码类
    window下载安装solr及测试
    Eclipse Android 手机开发作业---心随指动
    Eclipse Android 手机开发作业---空中的气球
    python OpenCV 实现图片的医学处理
    python OpenCV 宽度测量
  • 原文地址:https://www.cnblogs.com/wzcsqaws/p/15731957.html
Copyright © 2011-2022 走看看