WePY框架

WePY框架

WePY 框架在开发过程中参考了 Vue 等现有框架的一些语法风格和功能特性,对原生小程序的开发模式进行了再次封装,更贴近于 MVVM 架构模式, 并支持ES6/7的一些新特性。

**1.**遍历使用驼峰命名 避免使用 开 头 , 以 开头,以 开头的标识符为WePY框架的内建属性和方法,可在javascript脚本中以this的方式直接使用。

**2.**小程序入口,页面,组件文件名的后缀为 .wpy 外链文件可以是其他后缀。

**3.**框架默认对小程序提供 API进行Promise处理 可以直接使用async/await修饰。

**4.**事件绑定的优化

原bindtap=“click” 替换为 @tap=“click”

原catchtap="click"替换为@tap.stop=“click”

原capture-bind:tap="click"替换为@tap.capture=“click” 事件捕获

原capture-catch:tap="click"替换为@tap.capture.stop=“click” 停止事件捕获

**5.**事件传参

原bindtap=“click” data-index="{{index}}" 替换为 @tap=“click({{index}})”

**6.**基于WePY的代码开发 接近于vue

示例:

import wepy from 'wepy'

export default class Index extends wepy.page{

// 页面模板绑定的数据

data = {
		name:"zhangsan",

        dataLink: {}
   };

// 事件处理函数

methods = {
	hclick() {}
}// 生命周期
onLoad() {}
}

**7.**组件化开发

用法跟vue一样

1.先es6 import引入

2.然后在components = { panel: panel} 声明

3.最后在页面中挂载

**8.**单文件模式

project

└── src

​ ├── pages

​ | ├── index.wpy index 页面逻辑、配置、结构、样式

​ | └── log.wpy log 页面逻辑、配置、结构、样式

​ └──app.wpy 小程序逻辑、公共配置、公共样式

9. 脚本介绍

1.小程序入口 app.wpy

<script>
    import wepy from 'wepy';
	export default class extends wepy.app{
        config= {
            "pages":[
                "pages/index/index"
            ],
            "window":{
                "backgroundTextStyle":"light",
                "navigationBarBackgroundColor": "#fff",
            	"navigationBarTitleText": "WeChat",
            	"navigationBarTextStyle": "black"
            }
        };
		onLaunch(){}
    }
</script>
<style lang="less"></style>

2.页面page.wpy

<script>
import wepy from 'wepy';
import Counter from '../components/counter';

export default class Page extends wepy.page {
    config = {};  // 页面配置对象 对应原生的page.json文件
    components = {counter1: Counter};

    data = {};
    methods = {};

    events = {}; // 事件处理函数对象,存放响应式组件之间通过$broadcast、$emit、$invoke所传递的事件的函数
    onLoad() {};
    // Other properties
}
</script>

<template lang="wxml">
    <view>
    </view>
    <counter1></counter1>
</template>

<style lang="less">
/** less **/
</style>

**10.**实例

import wepy from 'wepy';

// 声明一个App小程序实例
export default class MyAPP extends wepy.app {
}

// 声明一个Page页面实例
export default class IndexPage extends wepy.page {
}

// 声明一个Component组件实例
export default class MyComponent extends wepy.component {
}

页面实例和component实例

import wapy from 'wepy'
// export default class Mypage extends wepy.page{}
export default class Mycomponent extends wepy.component{
 customData = {} // 自定义数据
 customFunction(){} //自定义方法
 onLoad() {} //在page和component共用的生命周期函数
 onShow() {} //只在page中存在的生命周期函数
 config = {};// 只在page实例中存在配置数据  对应于原生的page.josn文件
 data ={} //页面所需数据均在这里声明,可用于模板数据绑定
 compoents={}//声明页面中所引用的组件,或声明组件中所引用的子组件
 mixins = [] //声明页面所引用的Mixin实例
 computed = {} //声明计算属性
 watch = {} //声明数据监听 watcher
 methods = {} //声明页面wxml中标签的事件处理函数 注意此处只用于声明页面wxml中标签的bind、catch事件,自定义方法需以自定义方法的方式声明
 events ={}//声明组件之间的事件处理函数
} 

特殊声明 wepy中的methods和vue中的用法不一样。wapy里的methods只能声明页面wxml标签的bind\catch事件(bindtap 事件绑定不会阻止冒泡事件向上冒泡,catchtap 事件绑定可以阻止冒泡事件向上冒泡)

import wepy from 'wepy'
export default class MyComponent extends wepy.component{
    methods = {
        bindtap() {},
        bindinput(){}
    }
    myFunction(){} // 自定义方法在methods对象外声明,与methods平级
}

**11.**组件

  1. 如果在页面中引入同一组件多次,这几个组件共用一个实例与数据当其中一个组件数据变化时另一个也会变化,避免此类问题则需要分配多个组件id和实例

    <template>
    	<view class="child1">
            <child></child>
    	</view>
    	<view>
        	<anotherchild></anotherchild>
        </view>
    </template>
    <script>
    	import wepy from 'wepy'   
        import child from '../路径'
    	export default class Index extends wepy.component{
            components = {
                //为两个相同组件的不同实例分配不同的组件ID 从而避免数据同步变化问题
                child: child,
                anotherchild: child
            }
        }
    </script>
    

    WePY中,在父组件template模板部分插入驼峰式命名的子组件标签时,不能将驼峰式命名转换成短横杆式命名(比如将childCom转换成child-com),这与Vue中的习惯是不一致。

    2.组件的循环渲染

    当循环渲染wepy组件时,必须使用wepy定义的辅助标签

    <template>
    	<repeat for="{{list}}" key="index" index="index" item="item"> 
            //插入script脚本部分所申明的child组件 同时传入item
            <child :item="item"></child>
        </repeat>  
    </template>
    <script>
    	import wepy from 'wepy'
    	import Child from '../路径'
    	export default class Index extends wepy.component{
            components = {
                child:Child
            }
    		data = {
                list: [{id:1,name:'lisi'},{id:2,name:'z'}]
            }
        }
    </script>
    

    页面可以引入组件,而组件还可以引入子组件。

    3.computed 计算属性

    computed计算属性是有返回值的函数 script脚本中通过this.计算属性名来引用,模板中通过{{计算属性名}}来绑定数据,只要组件中任何数据发生了变化所有的计算属性都会从新计算

    data ={
        a:1
    }
    // 脚本中通过this.myCom来引用  模板中通过{{myCom}}来插值
    computed = {
        myCom () {
            return this.a + 1
        }
    }
    

    4.watcher监听器

    通过watcher能够监听到任何属性的更新,监听器在watch对象中声明,类型为函数,函数名与需要被监听的data对象中的属性同名,每当被监听的属性改变一次,监听器函数就会被自动调用执行一次

    data = {
        num:1
    }
    //监听的函数名必须跟需要被监听的data对象中的属性num同名
    //其参数中的newValue为属性改变后的新值  oldValue为改变前的旧值
    watch = {
        num (newValue,oldValue) {}
    }
    //每当被监听的属性num改变一次 对应的同名监听器函数num()就会被自动执行一次
    onLoad () {
        setInterval(() =>{
            this.num++;
            this.$apply();
        },1000)
    }
    

    this.$apply()使用场景:

    1.异步更新数据

    2.手动刷新DOM

**12.**props传值

props传值再wepy中属于父子组件传值包括静态传值和动态传值

1.静态传值

父组件向子组件传递常量数据,因此只能传递string字符串类型

父组件中

<child title="mytitle"></child>

子组件 child.wpy

props = {
    title: String
};
onLoad() {
    console.log(this.title)  // mytitle
}

2.动态传值

动态传值就是父组件向子组件传递动态数据内容,父组件数据完全独立互不干扰。

01.可以通过使用.sync修饰符来达到父组件绑定至子组件

02.也可以通过设置子组件props的twoWay:true 来达到子组件数据绑定至父组件的效果。

03.既使用.sync修饰,同时子组件props中添加twoWay:true 就可以实现数据的双向绑定(twoWay为false时表示子组件不向父组件传值)

父组件中

<child :title="parentTitle" :syncTitle.sync="parentTitle" :twoWayTitle="parentTitle"></child>
// 父组件数据项
data = {
    parentTitle: 'p-title'
}

子组件中

props ={
    //静态传值
    title: String,
    //父向子单向动态传值
    syncTitle: {
        type: string,
        default: 'null'
    },
    //父子双向动态传值
    twowayTitle: {
        type:Number,
        default: 'nothing',
        twoWay: true
    }
};
onLoad () {
    console.log(this.title);    // p-title
    console.log(this.syncTitle);   // p-title
    console.log(this.twoWayTitle);  // p-title
    
    this.title = 'c-title';
    console.log(this.$parent.parentTitle);  // p-title
    this.twoWayTitle = 'two-way-title';
    this.$apply();
    console.log(this.$parent.parentTitle); // two-way-title  --- twoWay为true时,子组件props中的属性值改变时,父也会改变
    this.$parent.parentTitle = 'p-title-changed';
    this.$parent.$apply();
    console.log(this.title); //c-title
    console.log(this.syncTitle); //  p-title-changed  --- 有.sync修饰符的props属性值,当在父组件中改变时,子也会改变
}

**13.**组件通信

wepy.component提供 e m i t 、 emit 、 emitbroadcast、$invoke三个方法用于组件之间通信,交互事件写在组件和页面的events对象中

this.$emit('some-event',1,2,3,4);
import wepy from 'wepy'
export default class Com extends wepy.component{
    events = {
        'some-event': (p1,p2,p3,$event) =>{}
    }
}

1.$broadcast 事件是由父组件发起,所有子组件都会收到此事件,除非手动取消。

2.$emit事件是由子组件发起,他的父组件,父组件的父组件都会收到此事件。

3.$invoke是一个页面或组件对另一个组件中的方法直接调用,通过传入组件路径找到相应的组件,然后调用其方法。

//在页面中调用comA的某个方法
this.$invoke('comA','someMethod')
//再组件comA中调用comG的某个方法
this.$invoke('组件comG路径''方法名')

**14.**组件自定义事件处理函数

@customEvent.user=‘myFn’

其中 @表示事件修饰符 customEvent 表示事件名称 .user表示事件后缀

三种事件后缀

.default 绑定小程序事件冒泡 如bindtap .default后缀可以省略 因为默认事件冒泡

.stop绑定小程序事件捕获 如catchtap

.user绑定小程序自定义事件,通过$emit触发。 如果用了自定义事件,则events中对应的监听函数不会再执行

父组件
<template>
	<child  @childFn.user="parentFn"></child>   
</template>
<script>
	import wepy from 'wepy'
	import Child from '路径'
	export default class Index extends wepy.page{
        compoents = {
            child: child
        }
		methods = {
            parentFn (num,evt) {
            }
        }
    }
</script>
子组件
<template>
	<view @tap="tap">点击我</view>    
</template>
<script>
	   import wepy from 'wepy'
	   export default class child extends wepy.component {
           methods = {
               tap() {
                   this.$emit('childFn',100)
               }
           }
       }
</script>

**15.**slot插槽 用法跟vue中具名插槽用法一致

公共组件 Panel
<view class="panel">
    <slot name="title">默认标题</slot>
	<slot name="content">默认内容</slot>
</view>
在父组件中使用公共组件
<panel>
	<view slot="title">一级标题</view>
	<view slot="content">
    	<text>内容</text>    
    </view>
</panel>

16.Mixin

1.混合开发

// mixins/test.js
import wepy from 'wepy';

export default class TestMixin extends wepy.mixin {
    data = {
        foo: 'foo defined by page',
        bar: 'bar defined by testMix'
    };
    methods: {
    tap () {
      console.log('mix tap');
    }
  }
}

// pages/index.wpy
import wepy from 'wepy';
import TestMixin from './mixins/test';

export default class Index extends wepy.page {
    data = {
        foo: 'foo defined by index'
    };
    mixins = [TestMixin ];
    onShow() {
        console.log(this.foo); // foo defined by index
        console.log(this.bar); // bar defined by testMix
    }
}

2.兼容式混合开发

先响应组件本身响应事件,然后再响应混合对象中响应事件。注意,这里事件的执行顺序跟Vue中相反,Vue中是先执行mixin中的函数, 再执行组件本身的函数

// mixins/test.js
import wepy from 'wepy';

export default class TestMixin extends wepy.mixin {
    methods = {
        tap () {
            console.log('mixin tap');
        }
    };
    onShow() {
        console.log('mixin onshow');
    }
}

// pages/index.wpy
import wepy from 'wepy';
import TestMixin from './mixins/test';

export default class Index extends wepy.page {

    mixins = [TestMixin];
    methods = {
        tap () {
            console.log('index tap');
        }
    };
    onShow() {
        console.log('index onshow');
    }
}


// index onshow
// mixin onshow
// ----- when tap
// index tap
// mixin tap

**17.**interceptor 拦截器

import wepy from 'wepy';

export default class extends wepy.app {
    constructor () {
        //拦截request请求
        this.intercept('request', {
            // 发出请求时的回调函数
            config (p) {
                // 对所有request请求中的OBJECT参数对象统一附加时间戳属性
                p.timestamp = new Date().getTime();
                console.log('config request: ', p);
                // 必须返回OBJECT参数对象,否则无法发送请求到服务端
                return p;
            },

            // 请求成功后的回调函数
            success (p) {
                // 可以在这里对收到的响应数据对象进行加工处理
                console.log('request success: ', p);
                // 必须返回响应数据对象,否则后续无法对响应数据进行处理
                return p;
            },

            //请求失败后的回调函数
            fail (p) {
                console.log('request fail: ', p);
                // 必须返回响应数据对象,否则后续无法对响应数据进行处理
                return p;
            },

            // 请求完成时的回调函数(请求成功或失败都会被执行)
            complete (p) {
                console.log('request complete: ', p);
            }
        });
    }
}

**18.**数据绑定

原生 通过setData({})

this.setData({title: 'this is title'});

wepy数据绑定方式

this.title = 'this is title';

注意异步函数中跟新数据必须手动调用$apply方法,才会触发脏数据检查流程

setTimeout(() => {
    this.title = 'this is title';
    this.$apply();
}, 3000);

**19.**请求优化

原生
wx.request({
    url:'xxx',
    data: {
        x: '',
        y: ''
  	},
    header: {
        'content-type': 'application/json' // 默认值
    },
    success (res) {
        console.log(res.data)
    }
})

wepy方式
import wepy from 'wepy';
// promise
wepy.getInfo(url,data)
.then(res => {
  console.log(res);
})
// async
async getSystem() {
  let res = await wepy.getInfo(url,data);
  console.log(res);
}

**20.**事件参数传递

原生
<view data-id="{{index}}" data-title="haha" data-other="lala" bindtap="hclick">点我</view>
page({
    hclick:function (e) {
        console.log(e.currentTarget.dataset.id) //1
    }
})

wepy  只允许传string类型
<view @tap="hclick({{index}},'haha','lala')">点我</view>
methods:{
    hclick (id,title,name,event) {
        console.log(id,title,name)
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值