微信小程序--逻辑层与界面层

一.逻辑层与界面层分离

小程序开发框架将我们需要完成的编码,划分成了两种类型的编码:逻辑编码(由JavaScript完成,业务数据供给界面事件处理),界面编码(页面结构WXML,页面样式WXSS,展示逻辑层的数据).

二.逻辑层的JavaScript

小程序开发中使用到的JavaScript同常规网页开发所使用的JavaScript有所差异,在小程序的开发之中,有很多的.js文件,他们都属于页面的逻辑层,我们知道程序一旦启动就会去执行app.js文件中的代码,我们可以使用console.log()方法来验证.
小程序不是运行在浏览器中,所以没有BOM和DOM对象,但是在小程序只用存在一些特有的全局成员:

 1 //app.js
 2 
 3 console.log("==============================");
 4 //自定义逻辑代码
 5 //1.小程序不是运行在浏览器中,所以没有BOM和DOM对象
 6 console.log(window); //在小程序中无法获取到BOM中定义的成员
 7 console.log(document); //无法获取到DOM中定义的成员
 8 //2.小程序的JS有一些额外的成员(全局)
 9 //App 方法:用于定义应用程序实例对象
10 //Page方法:用于定义页面对象
11 //getApp方法:用于获取全局应用程序对象,每个小程序都由唯一的应用程序实例
12 //getCurrentPages:用于获取当前页面的调用栈
13 //wx对象: 用来提供核心api
14 console.log(wx);
15 //3.小程序的JS是支持CommonJS规范(用于约定这些文件与文件之间是如何组织,相互之间协同的)的
16 //通过module 和 require来传递通用方法
17 const foo = require("./utils/foo.js");    
18 foo.say("world");
19 console.log("==============================");
20 var obj = {
21   onLaunch: function() {
22     // 展示本地存储能力
23     var logs = wx.getStorageSync('logs') || []
24     logs.unshift(Date.now())
25     wx.setStorageSync('logs', logs)
26 
27     // 登录
28     wx.login({
29       success: res => {
30         // 发送 res.code 到后台换取 openId, sessionKey, unionId
31       }
32     })
33     // 获取用户信息
34     wx.getSetting({
35       success: res => {
36         if (res.authSetting['scope.userInfo']) {
37           // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
38           wx.getUserInfo({
39             success: res => {
40               // 可以将 res 发送给后台解码出 unionId
41               this.globalData.userInfo = res.userInfo
42 
43               // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
44               // 所以此处加入 callback 以防止这种情况
45               if (this.userInfoReadyCallback) {
46                 this.userInfoReadyCallback(res)
47               }
48             }
49           })
50         }
51       }
52     })
53   },
54   globalData: {
55     userInfo: null
56   },
57   //自定义成员方法
58   foo: function() {
59       console.log("自定义成员方法");
60   }
61 };
62 //调用了一个APP方法(全局方法)
63 App(obj);
64 //调用App方法的作用是用来创建应用程序实例对象
65 //定义应用程序的生命周期事件
1 function say(msg){
2   console.log("hello " + msg);
3 }
4 
5 // 导出say()方法
6 module.exports = {
7   say: say
8 }
9 //在标准的COmmonJS规范中还支持exports.say 来导出,但是在小程序当中是不支持的,只支持module.exports
 1 //index.js
 2 //获取应用实例
 3 //完成页面的逻辑,包括功能的实现
 4 const app = getApp()
 5 
 6 Page({
 7   data: {
 8     motto: 'Hello World',
 9     userInfo: {},
10     hasUserInfo: false,
11     canIUse: wx.canIUse('button.open-type.getUserInfo')
12   },
13   //事件处理函数
14   bindViewTap: function() {
15     wx.navigateTo({
16       url: '../logs/logs'
17     })
18   },
19   onLoad: function () {
20     if (app.globalData.userInfo) {
21       this.setData({
22         userInfo: app.globalData.userInfo,
23         hasUserInfo: true
24       })
25     } else if (this.data.canIUse){
26       // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
27       // 所以此处加入 callback 以防止这种情况
28       app.userInfoReadyCallback = res => {
29         this.setData({
30           userInfo: res.userInfo,
31           hasUserInfo: true
32         })
33       }
34     } else {
35       // 在没有 open-type=getUserInfo 版本的兼容处理
36       wx.getUserInfo({
37         success: res => {
38           app.globalData.userInfo = res.userInfo
39           this.setData({
40             userInfo: res.userInfo,
41             hasUserInfo: true
42           })
43         }
44       })
45     }
46   },
47   getUserInfo: function(e) {
48     console.log(e)
49     app.globalData.userInfo = e.detail.userInfo
50     this.setData({
51       userInfo: e.detail.userInfo,
52       hasUserInfo: true
53     })
54   },
55   onShow: function () {
56     //在每次该界面唤醒时,获取当前页面的调用栈:
57     console.log(getCurrentPages());
58     console.log("当前调用栈中的页面数量: " + getCurrentPages());
59   }
60   
61 })
 1 // pages/demo/demo.js
 2 
 3 //获取当前小程序对象实例
 4 var app = getApp();
 5 Page({
 6 
 7   /**
 8    * 页面的初始数据
 9    */
10   data: {
11 
12   },
13 
14   /**
15    * 生命周期函数--监听页面加载
16    */
17   onLoad: function (options) {
18     app.foo();
19     
20   },
21 
22   /**
23    * 生命周期函数--监听页面初次渲染完成
24    */
25   onReady: function () {
26 
27   },
28 
29   /**
30    * 生命周期函数--监听页面显示
31    */
32   onShow: function () {
33     //在每次该界面唤醒时,获取当前页面的调用栈:
34     console.log(getCurrentPages());
35     console.log("当前调用栈中的页面数量: " + getCurrentPages());
36     console.log(getCurrentPages()[getCurrentPages().length - 1] == this);
37   },
38 
39   /**
40    * 生命周期函数--监听页面隐藏
41    */
42   onHide: function () {
43 
44   },
45 
46   /**
47    * 生命周期函数--监听页面卸载
48    */
49   onUnload: function () {
50 
51   },
52 
53   /**
54    * 页面相关事件处理函数--监听用户下拉动作
55    */
56   onPullDownRefresh: function () {
57 
58   },
59 
60   /**
61    * 页面上拉触底事件的处理函数
62    */
63   onReachBottom: function () {
64 
65   },
66 
67   /**
68    * 用户点击右上角分享
69    */
70   onShareAppMessage: function () {
71 
72   }
73 })

三.界面层--数据绑定

在程序的开发过程中,界面层提供一种模板机制,可以借助一种特殊的语法来完成数据的绑定,将动态的数据绑定到模板当中,最近将嵌入过后的数据显示到界面中,小程序中使用的是Mustache 语法(双大括号)语法:

1 
 2 
 3 
 7 
 8   {{ message }}
 9   {{ person.name }} : {{ person.age }}
10 
 1 // pages/demo/demo.js
 2 
 3 Page({
 4   //为页面提供数据,界面和逻辑之间的桥梁
 5   data:{
 6       message:"hello world",
 7       person:{
 8         name: "张三",
 9         age:25
10       }
11   }
12 })

--数据绑定语法补充,除了在页面标签的内部我们会使用Mustache语法进行输出,在标签的内部,我们也可以使用Mustache语法:

 1 
 2 
 3 
 7 
 8   {{ message }}
 9   {{ person.name }} : {{ person.age }}
10   
14   
15   
16   {{ 'hello' }}
17   {{ 111 }}
18   {{ 111 + 222 }}
19   {{ 111 < 222 ? 'yes' : 'no' }}
20   {{ true }}
21   
24   复选框1
25   复选框2
26 

四.列表渲染

在逻辑层中,很多的情况下都会是一个数组类型的数据(列表数据),那么此时在我们的界面层中就需要使用到列表渲染:

1   
 4   复选框1
 5   复选框2
 6   
 7   
 8     
20     
30     
31       {{ bbb + 1 }}:
32       
33       {{ item.name }} {{ aaa.name }}
34     
35     
36     
37       
38         
39           
40             {{ i }} * {{ j }} = {{ i * j }}
41           
42         
43       
44     
45   

五.事件处理

1   
3   
1   buttonTapHandle: function(e){
2     console.log("点击按钮打印此条.");
3     // console.dir()将一个对象以树状的形式打印到控制台,便于我们调试复杂对象
4     console.dir(e);
5   }

六.事件冒泡

1   
4   
5      
6   
1   innerHandler: function(){
2     console.log("触发内部事件");
3   },
4   outerHandler: function(){
5     console.log("触发外部事件");
6   }

七.事件传参

1   
8   
1   handleWithParm(e){
2     console.log(e);     //获取当前的点击元素
3     console.log(e.target.dataset);    //获取元素上所有data-[xxx]属性的集合
4   }

八.单向数据流

1   
4   
5     
6     {{ inputMessage }}
7   
 1   inputHandler: function(e) {
 2     //e.detail.value 获取到当前输入的值
 3     console.log(e.detail.value);
 4     //小程序中的数据绑定,本质上是一次绑定,在绑定完成之后,并不会去监视数据的变化.如果想要得到此次的变化,那么就需要使用setData的方法进行改变
 5     //setData是用来改变data数据的,与直接赋值区别在于setData可以通知界面作出变化,而直接赋值的话没有办法实现这一点(早期的JS无法实现)
 6     this.setData({
 7       inputMessage: "您输入的内容: " + e.detail.value
 8     })
 9     console.log(this.data.message);
10   }

九.登录页面案例

 1 
 2 
 3   
 4     
 6     
 8   
 9   
10     
11     
12   
13 
 1 // pages/login/login.js
 2 /* 实现登录界面
 3     1. 设计数据的结构(data属性)
 4     2. 将数据绑定到指定的元素上
 5  */
 6 Page({
 7   data: {
 8     username: "",
 9     password: ""
10   },
11   //用于处理登录按钮点击的事件
12   buttonLogin: function() {
13     console.log("执行登录事件");
14   },
15   //用于处理注册按钮点击的事件
16   buttonRegister: function() {
17     //1. 首先需要知道用户输入了什么
18     console.log(this.data.username + " " + this.data.password);
19     //2. 根据用户输入的值去判断
20     //3. 根据判断的结果做出响应
21     console.log("执行注册事件");
22   },
23   //用户输入用户名
24   usernameChangeHandler: function(e) {
25     this.setData({
26       username: e.detail.value
27     })
28   },
29   //用户输入密码
30   passwordChangeHandler: function(e) {
31     this.setData({
32       password: e.detail.value
33     })
34   }
35 })

十.抽象共同的事件处理函数

如我在我们的代码之中为每一个input标签都增加一个事件绑定函数,那么在我们的代码之中,将会存在很多的重复代码,为了避免这样的的情况,我们可以抽象共同的事件处理函数:

1 
 2 
 3   
 4     
 6     
 8   
 9   
10     
11     
12   
13 
1 // pages/login/login.js
 2 /* 实现登录界面
 3     1. 设计数据的结构(data属性)
 4     2. 将数据绑定到指定的元素上
 5  */
 6 Page({
 7   data: {
 8     username: "",
 9     password: ""
10   },
11   //用于处理登录按钮点击的事件
12   buttonLogin: function() {
13     console.log(this.data.username + " " + this.data.password);
14     console.log("执行登录事件");
15   },
16   //用于处理注册按钮点击的事件
17   buttonRegister: function() {
18     //1. 首先需要知道用户输入了什么
19     console.log(this.data.username + " " + this.data.password);
20     //2. 根据用户输入的值去判断
21     //3. 根据判断的结果做出响应
22     console.log("执行注册事件");
23   },
24   //用户输入用户名
25   // usernameChangeHandler: function(e) {
26   //   this.setData({
27   //     username: e.detail.value
28   //   })
29   // },
30   //用户输入密码
31   // passwordChangeHandler: function(e) {
32   //   this.setData({
33   //     password: e.detail.value
34   //   }),
35   //   console.log(e);
36   // }
37   //抽象上述两个方法,完成事件
38   inputChangeHandler: function(e) {
39     var key = e.target.dataset.name;
40     var value = e.detail.value;
41     var changed = {};
42     changed[key] = value;
43     this.setData(changed);
44   }
45 })

--除此之外,我们还可以使用表单的方式来进行数据的接收,这样可以免除这一些列复杂的操作:

1     
 2       
 4       
 6     
 7     
 8       
 9       
10     
1 //使用表单提交的方式来完成数据接收
2 loginSubmit: function(e){
3   console.log(e.detail.value);
4 }

十一.条件渲染

 1   
 2   
 3     
 4     
 5         面板中显示的内容
 6         面板中显示的内容
 7         面板中显示的内容
 8     
 9     
11     
12       面板中显示的内容1
13       面板中显示的内容2
14       面板中显示的内容3
15     
16     
19     
24   

十二.界面层(WXSS vs CSS)

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。即将所有设备都使用rpx为750设置为撑满屏幕宽度.

1 .demo {
2   width: 750rpx;
3   height: 200px;
4   background-color: red;
5 }

原文作者:灰色天空_graySky
原文链接:https://www.cnblogs.com/skykuqi/p/11735404.html

你可能感兴趣的:(微信小程序--逻辑层与界面层)