• 言简意赅,在拿了人家开源项目来跑的时候,有时会发现小程序开发工具自带的模拟器能请求到数据,这时候比较简单,直接在工具上的导航栏找到“工具--->项目详情”,然后如图红框勾上然后再编译就开源在...

    言简意赅,在拿了人家开源项目来跑的时候,有时会发现小程序开发工具自带的模拟器不能请求到数据,这时候比较简单,直接在工具上的导航栏找到“工具--->项目详情”,然后如图红框勾上


    然后再编译就开源在模拟器上正常看到请求数据了。

    ~~~那么然后你肯定想在手机微信上试下,于是你点了导航栏的"预览",扫了二维码,发现尼玛手机上获取不到数据,尴尬,这时候控制台会报一些什么域名配置错误,这个时候到 “微信公众平台“,步骤 设置--->开发设置--->服务器域名


    正常情况下只需要四个都填你的服务器根地址就好啦,然后回到开发工具,把刚才勾选的去掉,然后再次编译 预览,OK。可以正常手机调试了。

    那么这个原因应该是 在手机跑的时候 微信会和微信公众平台的服务区域名去进行域名检测,如果在代码里的域名和服务区配置的域名不一致或者根本没有配置域名的话就会请求服务器失败。

    展开全文
  • 相信做过微信小程序的都知道,官方给出的微信web开发工具上根本就无法加载node_modules包,即使可以加载,node_modules动辄几十M的大小,小程序的代码限制在1M以内,微信小程序的三个不足: 1无法调用npm包 2无法...

    相信做过微信小程序的都知道,官方给出的微信web开发工具上根本就无法加载node_modules包,即使可以加载,node_modules动辄几十M的大小,小程序的代码限制在1M以内,微信小程序的三个不足:

    1无法调用npm包

    2无法使用babel转吗

    3无法重用组件(像react那样重用组件功能)

    接下来给大家介绍一个相对完整的微信开发解决方案:

    Labrador:(目前最新版本为:0.6.12)

    github地址:https://github.com/maichong/labrador

    特点:

    1,使用Labrador框架可以使微信开发者工具支持加载海量NPM包

    2,支持ES6/7标准代码,使用async/await能够有效避免回调地狱

    3,组件重用,对微信小程序框架进行了二次封装,实现了组件重用和嵌套

    4,自动化测试,非常容易编写单元测试脚本,不经任何额外配置即可自动化测试

    5,使用Editor Config及ESLint标准化代码风格,方便团队协作

    当然了也有缺点,你看完会发现缺点

    首先系统全局安装nodejs和Labrador命令行工具。

    npm install -g labrador-cli

    查看当前labrador版本

    labrador -V

    新建一个目录,初始化项目

    labrador create mylabrador        # 初始化labrador项目 mylabrador是你的项目名字


    用Egret Wing3(这个IDE更适合开发微信小程序),打开labradordemo这个项目,

    开启代码自动转换功能

    labrador watch

    然后用微信开发着工具打开labradordemo项目下面的dist文件


    这个里面不需要做任何的编码工作,在下面的src目录作修改,会自动同步到微信开发者工具上面


    在src/pages/index新增一个index.json文件,主要内容为设置页面的title

    {
      "navigationBarTitleText": "主页",
      "enablePullDownRefresh": false
    }

    然后保存,会同步到微信开发者工具


    labrador 库对全局的 wx 变量进行了封装,将所有wx 对象中的异步方法进行了Promise支持, 除了同步的方法,这些方法往往以on*create*stop*pause*close* 开头或以 *Sync 结尾。在如下代码中使用 labrador 库。


    import wx, { Component, PropTypes }from'labrador';


    wx.wx;          // 原始的全局 wx 对象

    wx.app;         // 和全局的 getApp() 函数效果一样,代码风格不建议粗暴地访问全局对象和方法

    wx.currentPages // 对全局函数 getCurrentPages() 优雅的封装

    Component;      // Labrador 自定义组件基类

    PropTypes;      // Labrador 数据类型校验器集合


    wx.login;       // 封装后的微信登录接口

    wx.getStorage;  // 封装后的读取缓存接口

    //... 更多请参见 https://mp.weixin.qq.com/debug/wxadoc/dev/api/


    我们建议不要再使用 wx.getStorageSync() 等同步阻塞方法,而在async 函数中使用await wx.getStorage() 异步非阻塞方法提高性能,除非遇到特殊情况。



    app.js文件

    import request from 'al-request';
    import { setStore } from 'labrador-redux';
    import { sleep } from './utils/utils';
    import store from './redux';


    if (__DEV__) {
      console.log('当前为开发环境');
    }


    // 向labrador-redux注册store
    setStore(store);


    export default class {
      async onLaunch() {
        try {
          await sleep(100);
          await request('api/start');
        } catch (error) {
          console.error(error);
        }
        this.timer();
      }


      async timer() {
        while (true) {
          console.log('hello');
          await sleep(10000);
        }
      }
    }

    代码中全部使用ES6/7标准语法。代码不必声明 use strict ,因为在编译时,所有代码都会强制使用严格模式。

    代码中并未调用全局的 App() 方法,而是使用export 语法默认导出了一个类,在编译后,Labrador会自动增加App() 方法调用,所有请勿手动调用 App() 方法。这样做是因为代码风格不建议粗暴地访问全局对象和方法。


    Labrador的自定义组件,是基于微信小程序框架的组件之上,进一步自定义组合,拥有逻辑处理、布局和样式。

    项目中通用自定义组件存放在src/compontents 目录,一个组件一般由三个文件组成,*.js*.xml*.less 分别对应微信小程序框架的jswxmlwxss 文件。在Labardor项目源码中,我们特意采用了xml less 后缀以示区别。如果组件包含单元测试,那么在组件目录下会存在一个*.test.js 的测试脚本文件。

    0.6 版本后,支持*.sass*.scss 格式样式文件。


    自定义组件示例

    下面是一个简单的自定义组件代码实例:


    逻辑 src/compontents/todo/todo.js


    import { Component, PropTypes } from 'labrador-immutable';


    const { string, bool, func } = PropTypes;


    class Todo extends Component {
      static propTypes = {
        id: string,
        title: string,
        createdAt: string,
        finished: bool,
        finishedAt: string,
        onRemove: func,
        onRestore: func,
        onFinish: func
      };


      constructor(props) {
        super(props);
        this.state = {
          icon: props.finished ? 'success_circle' : 'circle',
          className: props.finished ? 'todo-finished' : ''
        };
      }


      onUpdate(props) {
        this.setState({
          icon: props.finished ? 'success_circle' : 'circle',
          className: props.finished ? 'todo-finished' : ''
        });
      }


      handleRemove() {
        this.props.onRemove(this.props.id);
      }


      handleFinish() {
        if (this.props.finished) {
          this.props.onRestore(this.props.id);
        } else {
          this.props.onFinish(this.props.id);
        }
      }
    }


    export default Todo;

    自定义组件的逻辑代码和微信框架中的page很相似,最大的区别是在js逻辑代码中,没有调用全局的 Page() 函数声明页面,而是用 export 语法导出了一个默认的类,这个类必须继承于Component 组件基类。

    相对于微信框架中的page,Labrador自定义组件扩展了 propTypesdefaultPropsonUpdate()setState()children() 等方法和属性,children()方法返回当前组件中的子组件集合,此选项将在下文中叙述。

    Labrador的目标是构建一个可以重用、嵌套的自定义组件方案,在现实情况中,当多个组件互相嵌套组合,就一定会遇到父子组件件的数据和消息传递。因为所有的组件都实现了setState 方法,所以我们可以使用this._children.foobar.setState(data)this.parent.setState(data) 这样的代码调用来解决父子组件间的数据传递问题,但是,如果项目中出现大量这样的代码,那么数据流将变得非常混乱。

    我们借鉴了 React.js 的思想,为组件增加了 props 机制。子组件通过 this.props 得到父组件给自己传达的参数数据。父组件怎样将数据传递给子组件,我们下文中叙述。

    onUpdate 生命周期函数是当组件的 props 发生变化后被调用,类似React.js中的 componentWillReceiveProps 所以我们可以在此函数体内监测props 的变化。

    组件定义时的 propTypes 静态属性是对当前组件的props参数数据类型的定义。defaultProps 选项代表的是当前组件默认的各项参数值。propTypesdefaultProps 选项都可以省略,但是强烈建议定义 propTypes,因为这样可以使得代码更清晰易懂,另外还可以通过Labrador自动检测props值类型,以减少BUG。为优化性能,只有在开发环境下才会自动检测props值类型。

    编译时默认是开发环境,当编译时候采用 -m 参数才会是生产模式,在代码中任何地方都可以使用魔术变量__DEV__ 来判断是否是开发环境。

    组件向模板传值需要调用 setState 方法,换言之,组件模板能够读取到当前组件的所有内部状态数据。

    0.6版本后,Component 基类中撤销了setData 方法,新增了setState 方法,这样做并不是仅仅为了像React.js,而是在老版本中,我们将所有组件树的内部状态数据和props全存放在page.data中,在组件更新时产生了大量的setData 递归调用,为了优化性能,必须将组件树的状态和page.data 进行了分离。


    布局 src/compontents/todo/todo.xml


    <view class="list-item flex-row items-center todo {{state.className}}">
      <icon class="todo-icon" type="{{state.icon}}" size="20" color="#999" catchtap="handleFinish"/>
      <view class="block flex todo-title {{state.className}}-title"> {{props.title}} </view>
      <view class="btn btn-small {{props.finished?'btn-gray-hollow':'btn-danger'}}" catchtap="handleRemove">删除</view>
    </view>

    XML布局文件和微信WXML文件语法完全一致,只是扩充了两个自定义标签 <component/><list/>,下文中详细叙述。

    使用 {{}} 绑定变量时,以props.*state.* 开头,即XML模板文件能够访问组件对象的propsstate


    样式 src/compontents/todo/todo.less

    @import 'al-ui';


    .todo {
      background: #fff;
      font-size: @font-size-medium;
    }


    .todo-icon {
      margin-right: 10px;
    }


    .todo-finished {
      background: @color-page;
    }


    .todo-finished-title {
      .gray;
      text-decoration: line-through;
    }

    虽然我们采用了LESS文件,但是由于微信小程序框架的限制,不能使用LESS的层级选择及嵌套语法。但是我们可以使用LESS的变量、mixin、函数等功能方便开发。


    页面

    我们要求所有的页面必须存放在 pages 目录中,每个页面的子目录中的文件格式和自定义组件一致,只是可以多出一个*.json 配置文件。


    页面示例

    下面是默认首页的示例代码:


    逻辑 src/pages/index/index.js


    import wx, { Component, PropTypes } from 'labrador-immutable';
    import { bindActionCreators } from 'redux';
    import { connect } from 'labrador-redux';
    import Todo from '../../components/todo/todo';
    import * as todoActions from '../../redux/todos';
    import { sleep } from '../../utils/utils';


    const { array, func } = PropTypes;


    class Index extends Component {
      static propTypes = {
        todos: array,
        removeTodo: func,
        restoreTodo: func,
        createTodo: func,
        finishTodo: func
      };


      state = {
        titleInput: '',
        finished: 0
      };


      children() {
        let todos = this.props.todos || [];
        let unfinished = [];
        let finished = [];
        if (todos.length) {
          unfinished = todos.filter((todo) => !todo.finished);
          finished = todos.asMutable()
            .filter((todo) => todo.finished)
            .sort((a, b) => (a.finishedAt < b.finishedAt ? 1 : -1))
            .slice(0, 3);
        }
        return {
          list: unfinished.map((todo) => ({
            component: Todo,
            key: todo.id,
            props: {
              ...todo,
              onRemove: this.handleRemove,
              onRestore: this.handleRestore,
              onFinish: this.handleFinish
            }
          })),
          finished: finished.map((todo) => ({
            component: Todo,
            key: todo.id,
            props: {
              ...todo,
              onRemove: this.handleRemove,
              onRestore: this.handleRestore,
              onFinish: this.handleFinish
            }
          }))
        };
      }


      onUpdate(props) {
        let nextState = {
          finished: 0
        };
        props.todos.forEach((todo) => {
          if (todo.finished) {
            nextState.finished += 1;
          }
        });
        this.setState(nextState);
      }


      async onPullDownRefresh() {
        await sleep(1000);
        wx.showToast({ title: '刷新成功' });
        wx.stopPullDownRefresh();
      }


      handleCreate() {
        let title = this.state.titleInput;
        if (!title) {
          wx.showToast({ title: '请输入任务' });
          return;
        }
        this.props.createTodo({ title });
        this.setState({ titleInput: '' });
      }


      handleInput(e) {
        this.setState({ titleInput: e.detail.value });
      }


      handleRemove = (id) => {
        this.props.removeTodo(id);
      };


      handleFinish = (id) => {
        this.props.finishTodo(id);
      };


      handleRestore = (id) => {
        this.props.restoreTodo(id);
      };


      handleShowFinished() {
        wx.navigateTo({ url: 'finished' });
      }


      handleShowUI() {
        wx.navigateTo({ url: '/pages/ui/index' });
      }
    }


    export default connect(
      ({ todos }) => ({ todos }),
      (dispatch) => bindActionCreators({
        createTodo: todoActions.create,
        removeTodo: todoActions.remove,
        finishTodo: todoActions.finish,
        restoreTodo: todoActions.restore,
      }, dispatch)
    )(Index);


    页面代码的格式和自定义组件的格式一模一样,我们的思想是 页面也是组件

    js逻辑代码中同样使用 export default 语句导出了一个默认类,也不能手动调用Page() 方法,因为在编译后,pages 目录下的所有js文件全部会自动调用Page() 方法声明页面。

    我们看到组件类中,有一个对象方法 children() ,这个方法返回了该组件依赖、包含的其他自定义组件,在上面的代码中页面包含了三个自定义组件listtitlecounter ,这个三个自定义组件的key 分别为listmottocounter

    children() 返回的每个组件的定义都包含两个属性,component 属性定义了组件类,props 属性定义了父组件向子组件传入的props 属性对象。

    页面也是组件,所有的组件都拥有一样的生命周期函数onLoad, onReady, onShow, onHide, onUnload,onUpdate 以及setState函数。

    componetspages 两个目录的区别在于,componets 中存放的组件能够被智能加载、重用,pages 目录中的组件在编译时自动加上 Page() 调用,所以,pages 目录中的组件不能被其他组件调用,否则将出现多次调用Page()的错误。如果某个组件需要重用,请存放在componets 目录或打包成NPM包。


    注意 虽然页面也是组件,虽然页面的代码格式和组件一模一样,但是运行时,getCurrentPages() 得到的页面对象page 并非pages目录中声明的页面对象,page.root 才是pages目录中声明的页面对象,才是组件树的最顶端。这里我们用了组合 模式而非继承模式。

    注意 所有组件的生命周期函数支持 async ,但默认是普通函数,如果函数体内没有异步操作,我们建议采用普通函数,因为async 函数会有一定的性能开销,并且无法保证执行顺序。当声明周期函数内需要异步操作,并且【不关心】各个生命周期函数的执行顺序时,可以采用async 函数。



    布局 src/pages/index/index.xml


    <view class="todo-list has-toolbar">
      <view class="list">
        <list key="list" name="todo"/>
      </view>
      <block wx:if="{{state.finished}}">
        <view class="group-header">已完成</view>
        <view class="list">
          <list key="finished" name="todo"/>
        </view>
        <view wx:if="{{state.finished>3}}" class="padding-h-xxlarge padding-top-large">
          <view class="btn btn-gray-hollow block" catchtap="handleShowFinished">查看全部已完成</view>
        </view>
      </block>
      <view wx:if="{{props.todos.length}}" class="gray padding text-right">总数 {{props.todos.length}} 已完成
        {{state.finished}}
      </view>
      <view wx:else class="msg">
        <icon class="msg-icon" type="info" size="80" color="#ccc"/>
        <view class="msg-title">当前没有任务</view>
        <view class="msg-desc">请在下方输入框中填入新任务然后点击新增</view>
      </view>
      <view class="toolbar toolbar-bottom padding-h-xsmall">
        <view class="form-group flex">
          <input class="form-control" type="text" placeholder="请输入新的任务" value="{{state.titleInput}}"
                 bindinput="handleInput"/>
        </view>
        <view class="btn btn-success btn-toolbar" catchtap="handleCreate">新增</view>
      </view>
      <view class="footer">
        <view>Powered by Labrador</view>
        <text class="link" catchtap="handleShowUI">AL UI</text>
      </view>
    </view>

    XML布局代码中,使用了Labrador提供的 <component/> 标签,此标签的作用是导入一个自定义子组件的布局文件,标签有两个属性,分别为key (必选)和name (可选,默认为key的值)。key 与js逻辑代码中的组件key 对应,name 是组件的目录名。key 用来绑定组件JS逻辑对象的children 中对应的数据, name 用于在src/componetsnode_modules 目录中寻找子组件模板。


    样式 src/pages/index/index.less


    @import 'al-ui';
    @import 'todo';


    .todo-list {
      
    }


    LESS样式文件中,我们使用了 @import 语句加载所有子组件样式,这里的@import 'list' 语句按照LESS的语法,会首先寻找当前目录src/pages/index/ 中的 list.less 文件,如果找不到就会按照Labrador的规则智能地尝试寻找src/componetsnode_modules 目录中的组件样式。

    接下来,我们定义了 .motto-title-text 样式,这样做是因为motto key 代表的title组件的模板中(src/compontents/title/title.xml)有一个view 属于title-text 类,编译时,Labrador将自动为其增加一个前缀motto- ,所以编译后这个view所属的类为title-text motto-title-text (可以查看dist/pages/index/index.xml)。那么我们就可以在父组件的样式代码中使用.motto-title-text 来重新定义子组件的样式。

    Labrador支持多层组件嵌套,在上述的实例中,index 包含子组件listtitlelist 包含子组件title,所以在最终显示时,index 页面上回显示两个title 组件。


    自定义组件列表


    逻辑 src/components/list/list.js

    import wx, { Component } from 'labrador';

    import Title from'../title/title';

    import Item from'../item/item';

    import { sleep } from'../../utils/util';


    export defaultclassListextendsComponent {


      constructor(props){

        super(props);

        this.state= {

          items: [

            { id:1, title:'Labrador' },

            { id:2, title:'Alaska' }

          ]

        };

      }


      children (){

        return {

          title:{

            component: Title,

            props: { text:'The List Title' }

          },

          listItems:this.state.items.map((item)=> {

            return {

              component: Item,

              key: item.id,

              props: {

                item: item,

                title: item.title,

                isNew: item.isNew,

                onChange: (title)=> {this.handleChange(item, title) }

              }

            };

          })

        };

      }


      asynconLoad() {

        awaitsleep(1000);

        this.setState({

          items: [{ id:3, title:'Collie', isNew:true }].concat(this.data.items)

        });

      }


      handleChange(item, title) {

        let items=this.state.items.map((i)=> {

          if(item.id== i.id){

            returnObject.assign({},i,{ title });

          }

          return i;

        });

        this.setState({ items });

      }

    }

    在上边代码中的 children() 返回的listItems 子组件定义时,是一个组件数组。数组的每一项都是一个子组件的定义,并且需要指定每一项的key 属性,key 属性将用于模板渲染性能优化,建议将唯一且不易变化的值设置为子组件的key,比如上边例子中的id


    模板 src/components/list/list.xml

    <viewclass="list">

      <componentkey="title"name="title"/>

      <listkey="listItems"name="item"/>

    </view>

    在XML模板中,调用 <list/> 标签即可自动渲染子组件列表。和<component/> 标签类似,<list/> 同样也有两个属性,keyname。Labrador编译后,会自动将 <list/> 标签编译成wx:for 循环。


    自动化测试

    我们规定项目中所有后缀为 *.test.js 的文件为测试脚本文件。每一个测试脚本文件对应一个待测试的JS模块文件。例如src/utils/util.jssrc/utils/utils.test.js 。这样,项目中所有模块和其测试文件就全部存放在一起,方便查找和模块划分。这样规划主要是受到了GO语言的启发,也符合微信小程序一贯的目录结构风格。

    在编译时,加上 -t 参数即可自动调用测试脚本完成项目测试,如果不加-t 参数,则所有测试脚本不会被编译到dist 目录,所以不必担心项目会肥胖。


    普通JS模块测试

    测试脚本中使用 export 语句导出多个名称以test* 开头的函数,这些函数在运行后会被逐个调用完成测试。如果test测试函数在运行时抛出异常,则视为测试失败,例如代码:

    // src/util.js

    // 普通项目模块文件中的代码片段,导出了一个通用的add函数

    export functionadd(a, b) {

      return a+ b;

    }

    // src/util.test.js

    // 测试脚本文件代码片段


    import assert from'assert';


    //测试 util.add() 函数

    export functiontestAdd(exports) {

      assert(exports.add(1,1)===2);

    }

    代码中 testAdd 即为一个test测试函数,专门用来测试add() 函数,在test函数执行时,会将目标模块作为参数传进来,即会将util.js 中的exports 传进来。


    自定义组件测试

    自定义组件的测试脚本中可以导出两类测试函数。第三类和普通测试脚本一样,也为 test* 函数,但是参数不是exports 而是运行中的、实例化后的组件对象。那么我们就可以在test函数中调用组件的方法或则访问组件的propsstate 属性,来测试行为。另外,普通模块测试脚本是启动后就开始逐个运行test* 函数,而组件测试脚本是当组件onReady 以后才会开始测试。

    自定义组件的第二类测试函数是以 on* 开头,和组件的生命周期函数名称一模一样,这一类测试函数不是等到组件onReady 以后开始运行,而是当组件生命周期函数运行时被触发。函数接收两个参数,第一个为组件的对象引用,第二个为run 函数。比如某个组件有一个onLoad 测试函数,那么当组件将要运行onLoad 生命周期函数时,先触发onLoad 测试函数,在测试函数内部调用run() 函数,继续执行组件的生命周期函数,run() 函数返回的数据就是生命周期函数返回的数据,如果返回的是Promise,则代表生命周期函数是一个异步函数,测试函数也可以写为async 异步函数,等待生命周期函数结束。这样我们就可以获取run()前后两个状态数据,最后对比,来测试生命周期函数的运行是否正确。

    第三类测试函数与生命周期测试函数类似,是以 handle* 开头,用以测试事件处理函数是否正确,是在对应事件发生时运行测试。例如:

    // src/components/counter/counter.test.js


    export functionhandleTap(c, run) {

      let num= c.data.num;

      run();

      let step= c.data.num- num;

      if (step!==1) {

        thrownewError('计数器点击一次应该自增1,但是自增了'+ step);

      }

    }

    生命周期测试函数和事件测试函数只会执行一次,自动化测试的结果将会输出到Console控制台。


    项目配置文件

    labrador create 命令在初始化项目时,会在项目根目录中创建一个.labrador 项目配置文件,如果你的项目是使用 labrador-cli 0.3 版本创建的,可以手动增加此文件。

    配置文件为JSON5格式,默认配置为:

    {

      "define":{

        "API_ROOT":"http://localhost:5000/"

      },

      "npmMap":{

        "lodash-es":"lodash"

      },

      "uglify":{

        "mangle": [],

        "compress": {

          "warnings":false

        }

      },

      "classNames": {

        "text-red":true

      },

      "env":{

        "development": {},

        "production": {

          "define":{

            "API_ROOT":"https://your.online.domain/"

          }

        }

      }

    }


    展开全文
  • WePY 是一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。框架的细节优化,Promise,Async Functions的引入都是为了能让开发小程序项目变得更加简单,高效。 ...

    wepy是由腾讯团队推出的小程序组件化开发框架,为什么一开始推出的时候不直接用这一套!?官网地址

    WePY 是一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。框架的细节优化,Promise,Async Functions的引入都是为了能让开发小程序项目变得更加简单,高效。

    特性:

    类Vue开发风格
    支持自定义组件开发
    支持引入NPM包
    支持Promise
    支持ES2015+特性,如Async Functions
    支持多种编译器,Less/Sass/Styus、Babel/Typescript、Pug
    支持多种插件处理,文件压缩,图片压缩,内容替换等
    支持 Sourcemap,ESLint等
    小程序细节优化,如请求列队,事件优化等

    安装使用

    安装(更新) wepy 命令行工具。

    npm install wepy-cli -g

    生成开发示例

    wepy new myproject

    开发实时编译

    wepy build --watch

    开发者工具使用

    使用微信开发者工具新建项目,本地开发选择dist目录。
    微信开发者工具–>项目–>关闭ES6转ES5。重要:漏掉此项会运行报错。(已踩中此坑)
    微信开发者工具–>项目–>关闭上传代码时样式自动补全 重要:某些情况下漏掉此项会也会运行报错。
    微信开发者工具–>项目–>关闭代码压缩上传 重要:开启后,会导致真机computed, props.sync 等等属性失效。#270
    项目根目录运行wepy build –watch,开启实时编译。

    WePY项目的目录结构

    ├── dist                   小程序运行代码目录(该目录由WePY的build指令自动编译生成,请不要直接修改该目录下的文件)
    ├── node_modules           
    ├── src                    代码编写的目录(该目录为使用WePY后的开发目录)
    |   ├── components         WePY组件目录(组件不属于完整页面,仅供完整页面或其他组件引用)
    |   |   ├── com_a.wpy      可复用的WePY组件a
    |   |   └── com_b.wpy      可复用的WePY组件b
    |   ├── pages              WePY页面目录(属于完整页面)
    |   |   ├── index.wpy      index页面(经build后,会在dist目录下的pages目录生成index.js、index.json、index.wxml和index.wxss文件)
    |   |   └── other.wpy      other页面(经build后,会在dist目录下的pages目录生成other.js、other.json、other.wxml和other.wxss文件)
    |   └── app.wpy            小程序配置项(全局数据、样式、声明钩子等;经build后,会在dist目录下生成app.js、app.json和app.wxss文件)
    └── package.json           项目的package配置

    .wpy文件的编译过程

    这里写图片描述

    WePY编译组件的过程
    这里写图片描述

    原生小程序支持js模块化,但彼此独立,业务代码与交互事件仍需在页面处理。无法实现组件化的松耦合与复用的效果。

    例如模板A中绑定一个bindtap=”myclick”,模板B中同样绑定一样bindtap=”myclick”,那么就会影响同一个页面事件。对于数据同样如此。因此,只有通过改变变量或者事件方法,或者给其加不同前缀才能实现绑定不同事件或者不同数据。当页面复杂之后就十分不利于开发维护。

    因此,在WePY中实现了小程序的组件化开发,组件的所有业务与功能在组件本身实现,组件与组件之间彼此隔离,上述例子在WePY的组件化开发过程中,A组件只会影响到A所绑定的myclick,B也如此。

    进行promise处理

    修复wx.request的并发问题
    原生代码:(十分容易发生回调地狱)

    onLoad = function () {
        var self = this;
        wx.login({
            success: function (data) {
                wx.getUserInfo({
                    success: function (userinfo) {
                        self.setData({userInfo: userinfo});
                    }
                });
            }
        });
    }

    基于WePY的代码:

    import wepy from 'wepy';
    
    async onLoad() {
        await wepy.login();
        this.userInfo = await wepy.getUserInfo();
    }

    在同时并发10个request请求测试时:

    不使用WePY:

    这里写图片描述
    这里写图片描述

    使用WePY后:
    这里写图片描述

    总结:这框架更多是处理了js和架构上的问题,对应wxml块没有作出处理,所以还需要用原生的写;没有提供一些常用实用引入即用的组件。利用这套结构可是弥补一些原生小程序的不足,支持promise和async/await等新特性;由于是支持组件化和类vue开发,所以页面开发可以做到更好的模块化;提供了computed、watcher、props等能力,提高了开发的效率,只要框架打起来,开发人员按部就班的开发对应的页面就可以!有条件用这个框架就尽量用吧,虽然要学习多一个东西,但是用它结合原生效果会比只写原生的好!

    案例:https://github.com/dyq086/wepy-mall
    这里写图片描述

    展开全文
  • 在申请微信小程序的时候,appID非常重要,只有在开发者工具中设置appID才能显示完整功能。 主文件夹下由三个文件是小程序必要的组成文件,分别是app.js,app.json,app.wxss,如下图 这三个文件的作用分别为: ...

    界面如图所示,左边为实时预览界面,中间为文件,右边为编辑区。client文件夹存放客户端文件,即我们需要配置的界面。server为与服务器交互及小程序的信息。可以左右拖动以改变窗口大小。在申请微信小程序的时候,appID非常重要,只有在开发者工具中设置appID才能显示完整功能。

           主文件夹下由三个文件是小程序必要的组成文件,分别是app.js,app.json,app.wxss,如下图

    这三个文件的作用分别为:

    app.js 此文件是小程序的脚本代码,可在这里监听小程序的声明周期,声明全局变量等。
    app.json 对小程序的全局配置,可配置小程序由哪几部分组成,窗口背景色、导航条样式、标题等。
    app.wxss 整个小程序的公共样式表,可以在页面组件的class属性上直接使用。

    pages文件夹顾名思义是存放小程序的页面组成的,每个页面在创建时都由开发者工具生成四个文件:xxx.json、xxx.js、xxx.wxml、xxx.wxss。wxss文件如果不配置将采用默认公共样式。xxx.js和xxx.wxml是必要的,学过前端开发的就知道html和css层叠样式表,其实这些文件就是和前端的差不多的,wxml用来配置页面的布局和内容,wxss大部分继承了css中的属性和选择器,只是有些许不同。页面中的js、wxss等文件覆盖外层,也就是说页面中的优先级高。在页面的创建中,可以手动创建文件,也可配置后工具自动创建。创建方法为:在主文件夹的app.json下的pages中按格式补上页面名称,然后编译即可。

           

    上边的导航栏功能都顾名思义,右边上传测试功能时应选体验版,详情部分可查看小程序的具体信息及配置属性。

    上图为云开发控制台,需要连接网络,监测小程序的运营情况以及数据库等信息。

     

     

     

    展开全文
  • 几年前无意间接触了微信公众平台开发,这个在当时还是一个新鲜的事物,但现在已经很流行了,发展的类型也特别的多,比如订阅号、服务号、小程序、微信企业号等,这些产品在人们日常的生活与开发中,都是非常常见的。...

    几年前无意间接触了微信公众平台开发,这个在当时还是一个新鲜的事物,但现在已经很流行了,发展的类型也特别的多,比如订阅号、服务号、小程序、微信企业号等,这些产品在人们日常的生活与开发中,都是非常常见的。

    当时的博主也顺应时代的变化,去尝试着开发公众平台,到目前为止也算得上是得心应手了吧,但平时我不会去开发这种东西,因为我的本职是做Android开发的,所以我会选择在下班或休息时间去专研一下,当然付出是肯定的,目的不是收获,而是积累更多的新知识。最近博主总结了前面做过的微信公众号开发、微信企业号开发的一些思绪,为大家谋了一些福利吧,就是之前写的一些资源需要CSDN下载积分,或者视频教学需要钱,但这次博主抽出时间,把企业号开发相关的接口全部整合优化了一遍,也就是WeChatEnterprise框架了。

    回首前面几年我的成果,博主并不觉得自己是什么大神,是跟你们一样的菜鸟,打工仔一枚,只是平时喜欢专研一些技术相关的东西罢了。

    最初的源码资源成果,从最初的三次下载量,达到了2450多次,好评率80%以上,但是博主后面发现这个资源莫名其妙的从下载5积分涨到了30积分,还有就是文件有时候下载下来是个rar不带任何后缀,这个是CSDN的问题,绝对不是博主的问题,毕竟30积分对不常玩CSDN的人来说,还是有点高的。

     

     

    跟CSDN合作的企业号开发视频教学也收获了22740多学员,这也是让我感到很欣慰的,但是出于博主个人的原因,这个视频博主个人觉得是不合格的,因为声音常小而且还带着腼腆,感觉很对不起付费的学员,所以现在准备做一些东西来弥补这个问题,那就是这个懒人式的部署开发框架WeChatEnterprise

     

     

    后面博主不推荐大家再去购买这个课程,主要是音质真的不好,加上博主初次做视频,效果真的非常不好,所以不推荐大家再去学习视频,直接使用懒人框架开发学习完全够用了,良心推荐这个懒人式的部署开发框架WeChatEnterprise

    就连博主新出版的书也是用这个懒人式的部署开发框架WeChatEnterprise开发的,里面几乎覆盖了95%以上的开发接口,以及它们的调用、使用。

    新书发布地址:https://blog.csdn.net/jspping/article/details/82766456

    随便举个栗(例)子,如OAuth2授权、二次验证等

    首先看OAuth2授权,这个也全部都封装好了,可以直接使用。

    授权结果:

    再来看二次验证:

     

    二次验证的结果:

    当然这些只是其中的一部分,其他的接口都是已经封装好的,只需要替换对应的参数即可直接拿来使用。

    接下来回到正题,介绍懒人式的部署开发框架WeChatEnterprise的正确使用:

    ①首先要确保你的服务器已经搭建好,然后替换微信官方提供解决java.security.InvalidKeyException:illegal Key Size异常的jar包。

    jar下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html,下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
    如果安装了JRE,将两个jar文件放到%JRE_HOME% \lib\security目录下覆盖原来的文件。如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件。

    ②从博主的GitHub上clone或下载框架代码,导入到开发工具,找到wx.api.WXApi类,将其中的Token、EncodingAesKey、CorpId、Secret参数全部填上自己实际开发的参数然后保存,注意Token、EncodingAesKey参数可到企业号后台随机生成也可自定义,但必须要两端参数完全一致。

    GitHub WeChatEnterprise 框架下载或clone地址:https://github.com/Mr-Jiang/WeChatEnterprise

    开发工具下载地址:http://www.engineer-jsp.cn/download/tools/tools.rar

    ③在开发工具中编译之前导入修改参数后的WeChatEnterprise 框架源码,并部署到你的服务器。随后进入到微信企业后台,单击“应用与小程序”选项,进入页面后,单击左侧“应用”选项,找到“自建”选项,单击你要开启API接收的自建应用,单击要开启API接收的自建应用后,进入到自建应用的详细页面,找到“接收消息”选项,单击“设置API接收”选项,进入到API接收消息页面,将随机生成或自定义的Token、EncodingAesKey一并填写在开启API接收消息的web页面内对应的方框。注意,此时填写的Token、EncodingAesKey必须要与WeChatEnterprise 框架源代码下wx.api.WXApi类的Token、EncodingAesKey完全保持一致,否则会一直验证失败。接下来在给大家介绍URL参数填写,这里默认填写http://你的服务器地址或域名地址/WeChatEnterprise/coreServlet,如果需要修改地址的组成,可以修改服务器的项目root目录,也就是你服务器默认访问的那个项目的首页面,servlet名称可修改WeChatEnterprise 框架源码下的WebRoot/WEB-INF/web.xml里servlet-mapping节点的子节点url-pattern,反正最终这个路径一定是外网下可以被访问到的,否则也是会一直提示验证失败。

    ④完成以上步骤之后,你离成功部署项目只差一步之遥了,在单击“保存”按钮之前,默认不勾选上报地理位置、上报进入应用事件,博主也不建议勾选,因为勾选后每次进入应用都要提示,很烦人,确认是否勾选之后单击“保存”按钮即可完成开启API接收,进行后续的消息收发、自定义菜单等接口的操作,部署项目至此就成功了。

    接下来继续给大家介绍WeChatEnterprise 框架的使用以及核心类的解读。

    wx.servlet.WXCoreServlet核心类,WeChatEnterprise框架的消息出入口

    再部署成功之后,所有的消息请求与收发都在wx.servlet.WXCoreServlet类,这个类将收到的消息进行校验,校验成功之后在解密,解密成功后将协议进行层级分发。该类也是消息的出口,对发送和响应出去的消息进行加密发送。

    wx.protocol.WXProtocolManager核心类,WeChatEnterprise框架的消息解析、管理、分发等

    在成功收到消息之后,wx.protocol.WXProtocolManager类首先对消息进行解析,数据无误之后将会对协议进行分发,依据消息类型将协议划分为WXTextProtocolWXImageProtocolWXVoiceProtocolWXVideoProtocolWXLocationProtocolWXLinkProtocolWXEventProtocol七大协议场景,即文本协议、图片协议、语音协议、视频协议、位置协议、链接协议、事件协议,其中事件协议WXEventProtocol下又进行了多层级的事件分发。七大协议场景继承自WeChatEnterprise框架的wx.protocol.WXBaseProtocol基础协议,也最终将响应的消息交由wx.protocol.WXBaseProtocol基础协议通过wx.protocol.WXProtocolManager类响应给wx.servlet.WXCoreServlet核心类,wx.servlet.WXCoreServlet核心类再将响应的消息进行加密并发送出去。

    wx.protocol.WXProtocolManager类协议分发的7大场景下,当某个场景所执行的流程全部完成后,由wx.protocol.WXBaseProtocol基础协议类releasProtocol方法将该场景释放,标志下一场景的开始。

    上述都是WeChatEnterprise框架最最核心的部分,其他部分都是独立开来的,是开发者主动调用并发送消息给关注者。

    接下来具体介绍WeChatEnterprise框架各个包的具体功能:

    package wx.api

                           ------ 定义了框架的全局常量、全局变量 :请求地址、Token、EncodingAesKey、CorpId、Secret、获取凭证、封装code请求地址等

    package wx.app

                           ------ 应用管理 :获取应用、设置应用、获取应用列表

    package wx.contact

                           ------ 通讯录管理 :成员管理、部门管理、标签管理

                                   1.成员管理 :创建成员、读取(获取)成员、更新成员、删除成员、批量删除成员、获取部门成员、获取部门成员详情、userid to openid、openid to userid、二次验证、邀请成员、获取外部联系人详情

                                    2.部门管理 :创建部门、更新部门、删除部门、获取部门列表

                                   3.标签管理 :创建标签、更新标签名字、删除标签、获取标签成员、增加标签成员、删除标签成员、获取标签列表

    package wx.encryption

                           ------ 消息的加解密校验、请求校验

    package wx.media 

                           ------ 素材管理 : 上传临时素材、获取临时素材、上传图片

    package wx.menu

                           ------ 自定义菜单 ------ 创建菜单、获取菜单、删除菜单

    package wx.msg

                           ------ 基础消息单元类 :文件、照片、MpNews、News、Text、TextCard、Video、Voice

    package wx.msg.chat.group

                           ------ 群聊 :创建群聊、修改群聊、获取群聊会话

    package wx.msg.push

                         ------- 消息推送:推送文本消息、推送图片消息、推送语音消息、推送视频消息、推送文件消息、推送文本卡片消息、推送news图文消息、推送mpnews消息

    package wx.msg.req 

                          ------ 发送(请求)消息:发送文本消息、发送图片消息、发送语音消息、发送视频消息、发送文件消息、发送文本卡片消息、发送news图文消息、发送mpnews消息

    package wx.msg.resp

                          ------ 被动响应(response) :响应文本消息、响应音乐消息、响应图片消息、响应音频消息、响应视频消息、响应图文消息

    package wx.oauth2 

                           ------ 授权:code换取成员信息、user_ticket换取用户信息

    package wx.protocol

                           ------ 协议核心 :协议解析、协议管理、协议分发、协议划分为7大场景、协议层级下发等

    package wx.servlet

                           ------ 请求响应入口 : 消息的请求与响应、二次验证、授权登陆、重定向等

    package wx.util

                           ------ 工具包 : IO异步与同步阻塞网络请求、核心消息工具类、线程池管理等

    如果你觉得博主写的代码框架不错并且对你的开发有帮助,请在GitHub的WeChatEnterprise仓库页面的右上角点击“Star”,对我的技术分享进行支持,将是我最大的动力,博主会继续分享更多优质的资源给大家。

    展开全文
  • 微信小程序开发框架】 1、官方框架MINA 小程序提供的开发框架为MINA框架,它类似于淘宝Weex、Vue框架。MINA框架通过封装微信客户端提供的文件系统、网络通信、任务管理、数据安全等基础功能,对上层提供一整套...
  • 微信公众号后台开发总结一、项目简介当前需要做一个公众号后台,前期需要实现的功能有:(1) 在用户关注公众号时便获取用户的信息同时还要将用户信息存入数据库。(2) 在用户给公众号发送消息时,后台能够对消息...
  • 看前几天的科技新闻,微信中的“跳一跳”小游戏从去年12月发布,截至到今年3月份已经积累了3.9亿玩家,这是一个多么恐怖的数字,“跳一跳”游戏带火了整个微信小游戏开发圈。微信小游戏是个什么东西呢?参考一下万能...
  • 微信支付前的准备工作 1 开发者资质认证  微信支付开发第一步就是使用公司管理者/高层帐号登录微信开放平台,进入“账号中心”,进行开发者资质认证,需要填写公司资料,包括但限于,公司注册号,公 司营业执照...
  • 使用DelphiXE2和Intraweb14.0.50进行微信开发
  • 微信小程序开发流程微信小程序开发前端框架mpvue的特性mpvue框架原理前期准备开发环境和工具创建第一个mpvue小程序如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定...
  • 刚入门微信小程序开发,只是用来开发一些小工具来使用,没有太深入的研究,就当做个笔记。微信小程序的开发方式有很多种,可以基于原生API开发,或者wepy框架等,其他的还有很多,暂且记录一下基于wepy的开发过程。...
  • 1.开发工具 cocos creator 1.9.1 2.开发语言 js 下面对开发内容进行说明。 1. 微信平台的判断。在开发过程中,会经常调用微信提供的原生方法。微信提供了一个wx的接口,在cocos中默认继承了该A...
  • 微信小游戏主要是在canvas上进行图片的渲染,以及通过js操作图片动态的刷新 微信小游戏开发笔记:   特点: 快速体验,段生命周期,转化率高 体验优于手机网页 需要下载或者注册 展望: 替代过重的Ap和...
  • 微信小程序开发者工具安装和创建小程序 (地图定位代码) 地图定位案例:最后附带小程序地图定位代码 小程序简介 小程序特点 体验好(编译超过1M) “无须安装,即用即走”的特性让微信小程序拥有着近乎原生App...
  • 小程序框架wepy文档Github地址wepy官网:https://tencent.github.io/wepy/index.html项目创建与使用安装wepy以下安装都通过npm安装安装 wepy 命令行工具。...开发实时编译。wepy build --watch 项目目录结构 ...
  • 微信公共平台和微博分享一样,也需要申请一个ID,来作为调起微信、分享到微信的唯一标识。 申请微信APPID可以到微信平台http://open.weixin.qq.com/app/list/?lang=zh_CN上申请。具体的申请流程网站上有很详细的...
  • 常用API开发技巧学习笔记第一章 认识微信小程序前后端分离的开发方式小程序的特点小程序对开发者的影响学习小程序需要的基础第二章 小程序环境搭建与开发工具介绍小程序开发环境 第一章 认识微信小程序   微信小...
1 2 3 4 5 ... 20
收藏数 6,252
精华内容 2,500