Code Monkey home page Code Monkey logo

tvfe / wxpage Goto Github PK

View Code? Open in Web Editor NEW
622.0 26.0 97.0 189 KB

WXPage 是一个极其轻量的微信小程序开发框架,其中的API蕴含了“极致页面打开速度的**”,为可维护性与开发效率而设计的功能,框架来自“腾讯视频”小程序的项目沉淀,框架对于小程序工程理念为不依赖额外构建,即引即用。腾讯视频播放器插件 =>

Home Page: https://github.com/tvfe/txv-miniprogram-plugin

License: MIT License

JavaScript 100.00%
wxpage miniapp

wxpage's Introduction

WXPage

npm version

WXPage 是一个极其轻量的微信小程序开发框架,其中的API蕴含了“极致页面打开速度的**”,为可维护性与开发效率而设计的功能,框架起源于“腾讯视频”小程序。

目录

使用

dist/wxpage.js 放置到你的项目目录下,例如: "lib/wxpage.js"。使用DEMO

var wxpage = require('./wxpage')

使用 CLI 初始化项目:

npm install wxpage-cli -g

wxpage init

类方法

const wxpage = require('/path/to/wxpage.js');
  • wxpage.A(def<Object>)

    程序定义方法:

    App.A({
    
    });
  • wxpage(def<Object>)

    页面定义方法:

    Page.P({
    
    });
  • wxpage.C(def<Object>)

    组件定义方法:

    Component.C({
    
    });
  • wxpage.on(key<String>, handler<Function>)

    监听APP与页面间的消息

  • wxpage.emit(key<String>, message<任意>)

    监听APP与页面间的消息

  • wxpage.off(key<String>, handler<Function>)

    取消监听APP与页面间的消息

程序

在小程序的入口文件 app.js 里定义

程序-定义

示例:

const { A } = require('./wxpage')
A({
  config: {
    route: '/pages/$page'   // $page 会被替换成页面名
  },
  onLaunch: function () {

  },
  onShow: function () {

  }
});

程序-生命周期

  • onAwake(time<Number>)

    小程序进入后台模式后再激活的时候触发。time是耗时。

程序-配置

wxpage所扩展的配置

A({
  config: {
    /*所有微信wxpage所需的配置*/
  }
});
  • route 必需

    页面目录的路由地址,$page会被替换为页面名。

route 支持数组,为多项路由的时候,必须搭配 resolvePath 使用,否则默认采用第一项作为路径还原。

  • routeFrozenTime 可选

    限制两次路由跳转的时间间隔,默认为 1000,可为 0

  • resolvePath(name<String>) 可选

    A({
    
      config: {
        route: ['/page/$page', '/pages/$page'],
        resolvePath: function (name) {
          return `/page/${name}`
        }
      }
    });
  • extendPageBefore(name, def, modules) 可选

    自定义扩展页面,在框架执行扩展之前。

  • extendPageAfter(name, def, modules) 可选

    自定义扩展页面,在框架执行扩展之后。

  • extendComponentBefore(def) 可选

    自定义扩展组件,在框架执行扩展之前。例如为每个组件挂在一个实例方法:

    A({
      config: {
        extendComponentBefore: function (def, { fns }) {
          fns.wrapFun(def.created, function () {
            this.request = function () {
              // ...
            }
          })
        }
      }
    });

组件

基于小程序原生组件方案的扩展,提供了父-子组件间的关系引用,一些实用的实例方法等

组件-定义

  • 构造方法、配置声明

{COMPONENT}.js

Component.C({
  data: {},
  attached: function () {
    /**
     * this.$root
     * this.$parent
     */
  }
});

{COMPONENT}.json

{
  "component": true
}
  • 使用

{PAGE}.json

{
  "usingComponents": {
    "{COMPONENT}": "/comps/{COMPONENT}/{COMPONENT}"
  }
}

{PAGE}.wxml

<custom-component binding="$" />

组件-实例方法

  • $set({...})

    this.setData({...})

  • $data()

    获取当前组件的 data 对象,同 this.data

  • $curPage()

    获取当前页面实例。取 getCurrentPages 的最后一个项。

  • $curPageName()

    获取当前页面实例对应的页面名。根据A.config.route 的配置解析当前页面实例的route。

    Notice: 由于基础库1.2.0以下不支持 Page.prototype.route,故不兼容场景只能取到空字符串

  • $on(key, handler)

    监听跨页面间的消息

  • $emit(key, data)

    派发页面间的消息

  • $off(key, handler)

    取消监听消息

  • $call(method, arg1, arg2[, ...])

    通过消息的方式调用父组件方法,方法不存在也不会报错

  • $route(pagename[, config]) => 别名 $navigate

    wx.navigateTo的封装。跳转到指定页面,pagename 可以带上 queryString, 例如

    this.$route('play?vid=xxx&cid=xxx');
  • $redirect(pagename[, config])

    wx.redirectTo的封装。跳转到指定页面, 替换页面,不产生历史,pagename 可以带上 queryString, 例如

    this.$redirect('play?vid=xxx&cid=xxx');
  • $switch(pagename[, config])

    wx.switchTab的封装。

  • $launch(pagename[, config])

    wx.reLaunch的封装。

  • $back([delta])

    wx.navigateBack的封装。

    this.$back();
  • $preload(pagename)

    提前预加载指定页面(会触发对应页面的onPreload声明周期)

    this.$preload('play?vid=xxx&cid=xxx');
  • $bindRoute()

同页面

  • $bindRedirect()

    $bindRoute, 绑定 $onRedirect

  • $bindSwitch()

    $bindRoute, 绑定 $onSwitch

  • $on(key, handler)

    监听跨页面间的消息

  • $emit(key, data)

    派发页面间的消息。

  • $off(key, handler)

    取消监听消息

  • $put(id, value)

同页面

  • $take(id)

同页面

组件-实例属性

  • $root

当前组件所属的页面组件实例 只在 attached, ready生命周期后生效

  • $parent

在组件内获取父组件实例引用

Component.C({
  attached: function () {
    this.$parent.data // 父组件
    this.$root.data   // 根组件,可能是父组件
  }
});
  • $refs

    指定了 ref 的子组件实例Map,在父组件获取子组件引用:

<custom-component binding="$" ref="customComp"/>
Page.P({
  onLoad: function () {
    this.$refs.customComp // 根据ref属性获取子组件的实例引用
  }
});
  • $cache

同页面缓存模块

  • $session

同页面缓存模块

页面

wxpage 为页面组件扩展了一些利于优化需求使用的声明周期方法与及实例方法

页面-定义

Page.P('{PNAME}', {
  data: {
    message: 'Hello MINA!'
  },
  onNavigate: function () {
    this.$preload('detail?id=xxx')
  },
  onLoad: function () {
  }
})

页面-生命周期

  • onPageLaunch()

    小程序第一次运行的时候调用,此时对应的页面并未被加载。

  • onAppLaunch(opts)

    App.onLaunch 触发时调用。 opts:

    • path String 打开小程序的路径
    • query Object 打开小程序的query
    • scene Number 打开小程序的场景值
  • onAppShow(opts)

    App.onShow 第一次触发时调用。只会触发一次,需要多次调用的请使用原生的 App.onShow opts:

    • path String 打开小程序的路径
    • query Object 打开小程序的query
    • scene Number 打开小程序的场景值
  • onAwake(time<Number>)

    小程序进入后台模式后再激活的时候触发。time是耗时。

  • onPreload(res)

    调用 this.$preload(url) 的时候触发,此时对应的页面并未被加载,res:

    {
      url: '', //完整的来源url
      query: {} //url上解析出来的查询参数
    }
    
  • onNavigate(res)

    页面间跳转开始时调用,此时对应的页面并未被加载,res:

    {
      url: '', //完整的来源url
      query: {} //url上解析出来的查询参数
    }
    

页面-实例属性

  • $name

    当前页面名称

  • $state

    页面的一些状态集合,有以下字段:

    • firstOpen <Boolean> 是否首个被小程序启动的页面
  • $cache

    本地缓存的封装, 方法如下:

    • set(key, value[, expire][, cb]) 如果传 cb 参数,会使用异步模式并回调,否则直接同步返回结果。
      • value 缓存数据,可以为对象
      • expire 缓存过期时间,单位为毫秒。如果为 true ,那么保持已存在的缓存时间,如果没有缓存,那么认为过期,不保存。
      • cb 可选,异步写的时候回调,接收参数:cb(err), err不为空代表失败。
    • get(key[, cb]) 如果传 cb 参数,会使用异步模式并回调
      • cb 可选,异步读的时候回调,接收参数:cb(err, data), err不为空代表失败。
    • remove(key[, cb]) 如果传 cb 参数,会使用异步模式并回调 (since v1.1.9)
      • cb 可选,异步删除的时候回调,接收参数:cb(err, data), err不为空代表失败。
    Page.P({
      onLoad: function () {
        // 同步写
        this.$cache.set('page_data', {
            name: '首页'
        })
        // 异步写
        this.$cache.set('page_data_another', {
            name: '首页'
        }, function (err) {
          // success or fail
        })
        var data = this.$cache.set('page_data') // {name : '首页'}
        // 异步读
        this.$cache.get('page_data', function (err, data) {
          // success or fail
          if (err) {
            console.log('Get data error', err)
          } else {
            console.log('Get data success', data)
          }
        })
        // 设定缓存时间,例如:1000 毫秒
        this.$cache.set('page_data', {
            name: '首页'
        }, 1000)
        setTimeout(()=> {
          // 保持上次缓存时间: 1000-200毫秒
          this.$cache.set('page_data', {
              name: '首页'
          }, true)
        }, 200)
      }
    });
  • $session

    使用本地缓存实现的session, 小程序退出后session会消失,适用于大数据对象的临时存储 方法如下:

    • set(key, value[, cb]) 如果传 cb 参数,会使用异步模式并回调
    • get(key[, cb]) 如果传 cb 参数,会使用异步模式并回调
    • remove(key[, cb]) 如果传 cb 参数,会使用异步模式并回调
    Page({
      onLoad: function () {
        this.$session.set('page_session_data', {
            name: '首页'
        })
      }
    });
  • $emitter

    页面内的消息模块,作用于当前页面实例与及引用的子组件实例,方法:

    • on 监听
    • emit 派发
    • off 取消监听
  • $refs

    指定了 ref 的子组件实例Map

页面-实例方法

  • $setData([prefix<String>, ]obj)

    指定 prefix 的时候可以为data的每一个项添加访问路径前缀。不传相当于 setData(obj)

  • $curPage()

    获取当前页面实例。取 getCurrentPages 的最后一个项。

  • $curPageName()

    获取当前页面实例对应的页面名。根据A.config.route 的配置解析当前页面实例的route。

    Notice: 由于基础库1.2.0以下不支持 Page.prototype.route,故不兼容场景只能取到空字符串

  • $route(pagename[, config]) => 别名 $navigate

    wx.navigateTo的封装。跳转到指定页面,pagename 可以带上 queryString, 例如

    this.$route('play?vid=xxx&cid=xxx');
  • $redirect(pagename[, config])

    wx.redirectTo的封装。跳转到指定页面, 替换页面,不产生历史,pagename 可以带上 queryString, 例如

    this.$redirect('play?vid=xxx&cid=xxx');
  • $switch(pagename[, config])

    wx.switchTab的封装。

  • $launch(pagename[, config])

    wx.reLaunch的封装。

  • $back([delta])

    wx.navigateBack的封装。

    this.$back();
  • $preload(pagename)

    提前预加载指定页面(会触发对应页面的onPreload声明周期)

    this.$preload('play?vid=xxx&cid=xxx');
  • $bindRoute()

    点击代理方法,绑定 $onRoute 逻辑,在元素上声明 data-url 作为跳转地址,支持切面方法:

    • data-before 跳转前执行
    • data-after 跳转后执行

    示例:

    <button
      bindtap="$bindRoute"
      data-url="/pages/play"
      data-before="onClickBefore"
    >click redirect</button>
  • $bindRedirect()

    $bindRoute, 绑定 $onRedirect

  • $bindSwitch()

    $bindRoute, 绑定 $onSwitch

  • $on(key, handler)

    监听跨页面间的消息

  • $emit(key, data)

    派发页面间的消息。

  • $off(key, handler)

    取消监听消息

  • $put(id, value)

    指定 id 存在一份数据,可以为任何类型,以供其它逻辑获取使用

  • $take(id)

    根据 id 获取数据,数据只能被存在一次,获取一次。如果只存放一次,第二次获取 会得到 null 。

    示例:

    this.$put('play:prefetch', new Promise(function (resolve, reject) {
      wx.request(url, function (err, data) {
        resolve(data)
      })
    }));
    this.$take('play:prefetch').then(function (data) {
      // get data
    });
    this.$take('play:prefetch'); // => null

谁在用

腾讯视频 王者荣耀攻略 何润锋工作室 腾讯大家 腾讯谷雨 火箭少女101
瞄一眼lite 草场地 头牌观点 拾音方音乐餐厅 doki小程序 布谷FM
腾讯视频-亲情版本

wxpage's People

Contributors

dragon-rider avatar mister-hope avatar miuchan avatar switer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wxpage's Issues

个人原因

代码片段

请问一下我这个问题出在哪?

补充:似乎我往下切基础库版本也不行了.....?我记得以前是好使的?大概有几个月没碰小程序了。。。。

再补充:心态崩了,在我的项目上,是模拟器好使,而真机不行。新建这个代码片段是哪个都不好使......
我传指针这个操作应该没问题啊?

再再补充:
我记得小程序进入界面在onLoad之前不是会执行一次深拷贝么?
所以问题是不是出现在......onNagivate的同时页面就已经执行页面对象的深拷贝了?我记得老版本的小程序对this的赋值是有效的啊?

onAppShow只执行一次

onAppShow 只在初始化页面时候调用一次,

image
看注释以及debug都不执行...
更改了调用了吗还是这边代码结构问题= =?

wxpage会不会再来个类似webpack的工具,用来单页面

主要是,json,js,css写三个文件还是有点麻烦,之后会不会出
还有就是我想问问腾讯谷雨和腾讯视频体验起来很不一样,感觉腾讯谷雨加载起来很快,很流畅,腾讯视频可能是因为功能太多了,在卡一点的手机上,谷雨要流畅很多,想问问谷雨有什么优化吗

this.$cache方法中不能调用$route么?

Page.P('index',{ onLoad(){ let that = this; // 异步读 this.$cache.get('page_data', function (err, data) { // success or fail if (err) { that.$route('setting') } else { console.log('Get data success', data) } }) } })

想请教下,如何扩展的生命周期

项目中有一个需求,我想扩展下生命周期来完成,想请教下你是如何实现扩展生命周期的,代码没看懂,不知道方便回答下吗?

实现预加载有问题***

当第一个页面调用preload的时候会提前加载第二个页面的数据?那如果当已经跳转到第二个页面时,预加载的数据还没有完全读取完毕,怎么办?是不是还得从头开始走一遍第二个页面的读取逻辑?有没有什么办法能让它读完呢?

大大,组件中(┬_┬) 有地方不太明白

最近在看大大的代码,想学习学习,用在自己的小程序,遇到了不明白的地方

<custom-component binding="$" ref="customComp"/>

大大上面那个,我在代码 component.js 找到了 对ref的地方

var refs = {}
def.attached = fns.wrapFun(def.attached, function () {
	var id = ++cid
	this.$id = id
	refs[id] = this
	this._$ref = this.properties.ref || this.properties._ref
	this.triggerEvent('ing', {
		id: this.$id,
		type: 'attached'
	})
})

似乎是给组件定义来一个 properties为ref,存为this。

但是不明白的地方是

这个 binding=“$” 是做什么,我搜了下那几个文件,没找到

不同page 可能有相同函数功能

小程序页面简单,不同页面可能会有部分相同的函数功能和部分相同的html(类似小程序template),单纯封装成组件,又过度设计和时间不允许,是不是可以提供一个接口暴露出page某个函数可以被其他page使用~

我现在采用的办法是提取到一个公共的common文件中,需要用到再export出来,或者可以探讨下提取到common才是合理的,再去做暴露的功能也是过度设计!!

谢谢

onAwake 函数内部 this 为null

如题 ,page页面内部 onAwake this 显示null;

另外page里面有个onAppShow, 这个函数只有当前页面从后台切换前台才会执行,和onAwake功能重叠了?

最新版的有个小BUG

在组件里执行vm.$data().xxxx无法获取数据,直接报错。
我在wxpage.js优化了下代码就都正常了,具体看截图。
原本是ctx[cid],调整之后的代码为ctx.data[cid] || {}
image

关于template 和 组件

请问你们对组件的描述怎么包含官方文档中所提到的 template 和 组件,这两者不是不同的概念吗

关于SessionKey的问题

  1. 得到的session_id是存储在全局数据中还是本地缓存中比较好?
  2. session_id的有效期是多长呢?

库中无用代码的优化

如果正常页面做跳转是会调用brige.js里的route函数,函数如下:

function route ({type}) {
	// url: $page[?name=value]
	return function (url, config) {
		var parts = url.split(/\?/)
		var pagepath = parts[0]
		if (/^[\w\-]+$/.test(pagepath)) {
			pagepath = (conf.get('customRouteResolve') || conf.get('routeResolve'))(pagepath)
		}
		if (!pagepath) {
			throw new Error('Invalid path:', pagepath)
		}
		config = config || {}
		// append querystring
		config.url = pagepath + (parts[1] ? '?' + parts[1] : '')
		redirector[type](config)
	}

这个时候函数只传了一个参数config,我不清楚大大是怎么考虑的,但是route函数没有被bridge.js导出,而且整个脚本内调用回调函数的时候,都没有传入第二个参数,所以我可以认为config是在函数内被初始化,内只有一个对象url。(此处是建议更改的第一个部分,我猜大大可能因为relaunch这种大大说不兼容的api当时做了这个最后没用上成了幽灵代码,而且我也的确没明白reLaunch怎么不兼容)。

redirector里面的函数是这样的:

      exportee.navigateTo = function (cfg) {
        console.log(cfg, arguments);
        return route('navigateTo', cfg, arguments)
      }
      exportee.redirectTo = function (cfg) {
        return route('redirectTo', cfg, arguments)
      }
      exportee.switchTab = function (cfg) {
        return route('switchTab', cfg, arguments)
      }
      exportee.reLaunch = function (cfg) {
        return route('reLaunch', cfg, arguments)
      }
      exportee.navigateBack = function () {
        return wx.navigateBack.apply(wx, arguments)
      }

从刚才的分析来看,那么cfg就是传入的config参数,arguments是一个元素为1的数组。aruments[0]===config,所以这里是第二个我没明白的地方,argument意义何在?

我加了一行在里面跑了一下,这个时候神奇的部分就来了。(因为我也不知道为什么)

      exportee.navigateTo = function (cfg) {
        console.log(cfg);
        console.log(arguments);
        return route('navigateTo', cfg, arguments)
      }

控制台打出:

config是

{url:"/module/....(后面我省略了)"}

arguments是

{
  0: {url:"module/....(后面我省略了)"}
  _proto_: ....
}

url前面的/不见了,所以这就是QQ会报错navigateTo:fail page "module/module1?From=%E9%A6%96%E9%A1%B5&aim=FAQ7&depth=1" is not found的原因。

所以我想请问这是什么问题?argument的特性么?

我已经查出来了,这TM是模拟器的问题。

希望能够将以前的template与JS引入以实现动态组件引入添加回来

在demo版本里,组件是通过在html中import和在js中require实现的,这样的组件虽然没有后续官方新增的自定义组件中很强的生命周期与配置选项(比如样式隔离,函数作用域的改变)但是却可以利用template的is动态特性动态根据自身逻辑按照用户需要动态引入template并进行渲染。现在改成官方的自定义组件后,组件只能在开发的时候写死,没法现场进行动态引入了,所以大大能不能恢复一下以前的component,以实现动态组件引入?

大大,组件调用有点问题

定义了一个弹层的组件
在pageAd页面引用了,点击调用没问题,然后调用了$route,打开了pageB,点击调用也没问题,从pageB返回到pageA后,pageA点击就调用不了

大大,代码有两处好像有点小问题

因为我们的项目是 很多目录层级这样,看之前的issues,似乎不太适合,因此想改改,看代码过程中有几点疑惑

大大 一个是 可能监听了无效事件,根源在redirector.route 方法永远只 emit navigateTo事件
因此在bridge也只emit navigateTo 事件,
因此 option.onNavigate 下 就 dispatcher.on('navigateTo:'+name, onNavigateHandler) 起作用,虽然不影响,因为反正都执行


还有就是 component 下 ,那个name 感觉是 undefined,

function component(def) {
if (!def) {
	// ERROR name is underfined
	console.error(`Illegal component options [${name || 'Anonymous'}]`)
	def = {}
}

component.js 中 bridge.ref(component.getRef) 和 page.js 下bridge.ref(C.getRef) 是不是重复了


message.js 下 assign

  ['on', 'off', 'wait', 'emit', 'assign']

执行到 wait应该是undefined,不晓得,我猜的


还有大大, 下面的代码这种写法看不懂 brideg.js的route

pagepath = (conf.get('customRouteResolve') || conf.get('routeResolve'))(pagepath)

this.$setData() 方法无效

按照文档引入dist代码:

var P = require('../lib/wxpage')
var Header = require('../comps/header')

P('index', {
	comps: [
		Header,
	],
	data: {
		userName: '张三'
	},
	onLaunch: function () {
		console.log('## On index page launch')	
		this.$setData({
			userName:  '李四'
		})
	}
})

请问extendPageBefore和extendPageAfter的区别以及注意事项?

目前框架应该是在小程序载入,先执行APP的onLuanch和onShow,首屏onload之前就会执行主包的扩展,之后执行所有主包的onPageLaunch,之后是首屏的onload?在触发分包界面的时侯先执行分包的扩展,之后执行所有分包页的onPageLaunch,然后是分包对应界面的周期函数?

请问我上面说的对么?

所以这两个方法的具体执行时间是什么时候呢?我感觉不到这两个方法有什么区别啊

补充:灵机一动,是一个不会覆盖同名函数,一个会覆盖同名函数么?求大大现身说法。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.