http://blog.csdn.net/zuoliangzhu/article/details/53862576#t1

项目结构

└─ empty-folder/ ·································· 项目所在目录
   ├─ pages/ ······································ 页面目录
   │  ├─ index/ ··································· index页面
   │  │  ├─ index.js ······························ index页面逻辑
   │  │  ├─ index.wxml ···························· index页面结构
   │  │  └─ index.wxss ···························· index页面样式
   │  └─ logs/ ···································· logs页面
   │     ├─ logs.js ······························· logs页面逻辑
   │     ├─ logs.wxml ····························· logs页面结构
   │     └─ logs.wxss ····························· logs页面样式
   ├─ utils/ ······································ 公共脚本目录
   │  └─ util.js ·································· 工具脚本
   ├─ app.js ······································ 应用程序逻辑
   ├─ app.json ···································· 应用程序配置
   └─ app.wxss ···································· 应用程序公共样式

页面结构

每个页面组件也分为四个文件组成:

[page-name].js

页面逻辑文件,用于创建页面对象,以及处理页面生命周期控制和数据处理

[page-name].json

设置当前页面工作时的window的配置,此处会覆盖app.json中的window设置,也就是说只可以设置window中设置的属性

[page-name].wxml
wxml指的是Wei Xin Markup Language

用于定义页面中元素结构的,语法遵循XML语法,注意是XML语法,不是HTML语法

[page-name].wxss
wxml指的是Wei Xin Style Sheet

用于定义页面样式的,语法遵循CSS语法,扩展了CSS基本用法和长度单位(主要就是rpx响应式像素)

项目配置

小程序中的配置文件分为两种:

  • 全局配置文件,根目录下的app.json
  • 页面配置文件,每个页面目录下的[page-name].json
app.json

项目配置声明文件(指定项目的一些信息,比如导航栏样式颜色等等)

{
  // 当前程序是由哪些页面组成的(第一项默认为初始页面)
  // 所有使用到的组件或页面都必须在此体现
  // https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html#pages
  "pages": [ ... ],
  // 应用程序窗口设置
  // https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html#window
  "window": { ... },
  // 应用导航栏设置
  // https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html#tabBar
  "tabBar": { ... },
  // 网络超时设置
  // https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html#networkTimeout
  "networkTimeout": {},
  // 是否在控制台输出调试信息
  // https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html#debug
  "debug": true
}
[page-name].json

用于指定特定页面工作时,window的设置:

{
  // 导航条背景色
  "navigationBarBackgroundColor": "#35495e",
  // 导航条前景色(只能是white/black)
  "navigationBarTextStyle": "white",
  // 导航条文本
  "navigationBarTitleText": "电影 « 豆瓣",
  // 窗口背景颜色
  "backgroundColor": "#fff",
  // 窗口前景色
  "backgroundTextStyle": "dark",
  // 是否开启下拉刷新
  "enablePullDownRefresh": true
}

逻辑层分析

应用程序逻辑app.js

app.js作为项目主入口文件,用于创建应用程序对象

// App函数是一个全局函数,用于创建应用程序对象
App({
  // ========== 全局数据对象(可以整个应用程序共享) ==========
  globalData: { ... },

  // ========== 应用程序全局方法 ==========
  method1 (p1, p2) { ... },
  method2 (p1, p2) { ... },

  // ========== 生命周期方法 ==========
  // 应用程序启动时触发一次
  onLaunch () { ... },

  // 当应用程序进入前台显示状态时触发
  onShow () { ... },

  // 当应用程序进入后台状态时触发
  onHide () { ... }
})

也就是说,当应用程序启动时会自动执行项目目录下的app.js文件。

app.js中通过调用全局App([option])方法创建一个应用程序实例。

其中通过参数指定的一些特定的方法,会在特定的执行时机去执行,也就是说通常所说的生命周期事件方法。

属性类型描述触发时机
onLaunch Function 生命周期函数--监听小程序初始化 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
onShow Function 生命周期函数--监听小程序显示 当小程序启动,或从后台进入前台显示,会触发 onShow
onHide Function 生命周期函数--监听小程序隐藏 当小程序从前台进入后台,会触发 onHide

也可以定义任意其他的对象成员(例如:方法和属性),这些成员可以在内部直接使用,或者外部通过获取app对象调用:

属性类型描述
其他 Any 开发者可以添加任意的函数或数据到 Object 参数中,用 this 可以访问,一般用于存放业务逻辑配置,比如:API地址

app.js

App({
  data1: '123',
  data2: { message: 'hello world' },
  api: {
    list: 'https://github.com/zce/',
    detail: 'https://github.com/zce/',
  },
  foo () {
    return 'bar'
  }
})

other.js  

// getApp 也是全局函数,可以在任意地方调用,用于获取全局应用程序实例对象
var app = getApp()
console.log(app.data1)
console.log(app.data2)
console.log(app.foo())

页面逻辑[page-name].js

[page-name].js是一个页面的重要组成部分,用于创建页面对象

// 获取全局应用程序对象
const app = getApp()

// Page也是一个全局函数,用来创建页面对象
Page({
  // ========== 页面数据对象(可以暴露到视图中,完成数据绑定) ==========
  data: { ... },

  // ========== 页面方法(可以用于抽象一些公共的行为,例如加载数据,也可以用于定义事件处理函数) ==========
  method1 (p1, p2) { ... },
  method2 (p1, p2) { ... },

  // ========== 生命周期方法 ==========
  // 页面加载触发
  onLoad () { ... }

  ...
})

在应用程序执行到当前页面时,会执行当前页面下对应的[page-name].js文件。
[page-name].js中通过调用全局Page([option])方法创建一个页面实例。

Page([option])方法[option]参数说明
属性类型描述
data Object 页面的初始数据
onLoad Function 生命周期函数--监听页面加载
onReady Function 生命周期函数--监听页面初次渲染完成
onShow Function 生命周期函数--监听页面显示
onHide Function 生命周期函数--监听页面隐藏
onUnload Function 生命周期函数--监听页面卸载
onPullDownRefreash Function 页面相关事件处理函数--监听用户下拉动作
其他 Any 开发者可以添加任意的函数或数据到 object 参数中,用 this 可以访问

视图层分析

[page-name].wxml页面结构

WXML(WeiXin Markup Language)MINA框架设计的一套标签语言,基于XML

结合一些基础组件、事件系统、模板数据绑定,可以构建出页面的结构。

简单来说:wxml ≈ xml + 事件系统 + 模板引擎

例如

// js
Page({
  data: {
    todos: [
      { text: 'JavaScript', completed: false },
      { text: 'JavaScript+', completed: false },
      { text: 'JavaScript++', completed: false }
    ]
  },
  completed (e) { ... }
})
<!-- wxml -->
<view>
  <view wx:for="{{ todos }}">
    <block wx:if="{{ !item.completed }}">
      <text>{{ item.text }}</text>
      <button bindtap="completed" data-item-index="{{ index }}"> √ </button>
    </block>
  </view>
</view>

[page-name].wxss页面样式

WXSS(WeiXin Style Sheets)MINA框架设计的一套标签语言,基于XML

WXSS用来决定了在WXML中定义的组件应该怎么显示。

为了适应广大的前端开发者,我们的WXSS具有CSS大部分特性。 同时为了更适合开发微信小程序,我们对CSS进行了扩充以及修改。

CSS相比我们扩展的特性有:

  • 尺寸单位
  • 样式导入(CSS也有)
尺寸单位

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

rem(root em): 规定屏幕宽度为20rem;1rem = (750/20)rpx 。

设备rpx换算px (屏幕宽度/750)px换算rpx (750/屏幕宽度)rem换算rpx (750/20)
iPhone5 1rpx = 0.42px 1px = 2.34rpx 1rem = 37.5rpx
iPhone6 1rpx = 0.5px 1px = 2rpx 1rem = 37.5rpx
iPhone6s 1rpx = 0.552px 1px = 1.81rpx 1rem = 37.5rpx
  • 建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
  • 注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。
样式导入

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。

@import "common.wxss";
text {
  background-color: #ff0;
}
选择器

目前只支持如下选择器

选择器样例样例描述
.class .intro 选择所有拥有 class="intro" 的组件
#id #firstname 选择拥有 id="firstname" 的组件
element view 选择所有 view 组件
element, element view checkbox 选择所有文档的 view 组件和所有的 checkbox 组件
::after view::after 在 view 组件后边插入内容
::before view::before 在 view 组件前边插入内容
全局样式与局部样式

定义在app.wxss中的样式为全局样式,作用于每一个页面。在[page-name].wxss文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖app.wxss中相同的选择器。

列表页实例代码:

<!--lists.wxml-->
<view class="warp">

<!--文章列表模板 begin-->
<template name="itmes">
  <navigator url="../../pages/detail/detail?id={{id}}" hover-class="navigator-hover">   //跳转到指定id的页面
    <view class="imgs"><image src="{{img}}" class="in-img" background-size="cover" model="scaleToFill"></image></view>
    <view class="infos">
      <view class="title">{{title}}</view>
      <view class="date">{{cTime}}</view>
    </view>
  </navigator>
</template>
<!--文章列表模板 end-->

<!--循环输出列表 begin-->
<view wx:for="{{newsList}}" class="list">
  <template is="itmes" data="{{...item}}" />
</view>
<!--循环输出列表 end-->
<loading hidden="{{loadHidden}}" bindchange="loadChange">
    数据加载中...
</loading>
<!--bindtap 点击事件-->
<view bindtap="loadMore" data-lastid="{{lastid}}" data-isfrist="{{isfrist}}" class="loadMore" style="display:{{moreHidden}}">加载更多</view>
<toast hidden="{{toastHidden}}" bindchange="toastChange" duration="3000">{{msg}}</toast>
<modal title="温馨提示" no-cancel hidden="{{confirmHidden}}" confirm-text="明确" bindconfirm="modalChange">你当前不在在WIFI网格下下,会产生流量费用</modal>
</view>
// lists.wxss
.warp{
    height: 100%;
    display: flex;
    flex-direction: column;
    padding: 20rpx;
}
navigator { overflow: hidden;}

.list {margin-bottom: 20rpx;height: 200rpx;position: relative;}
.imgs {float: left;}
.imgs image {display: block; width: 200rpx;height: 200rpx;}

.infos {float: left; width: 480rpx; height: 200rpx;padding: 20rpx 0 0 20rpx;}
.title {font-size: 20px;}
.date {font-size: 16px;color: #aaa; position: absolute;bottom: 0;}

.loadMore {text-align: center;margin: 30px;color: #aaa;font-size: 16px}
//lists.js
//获取应用实例
var app = getApp()
Page({
  data: {
    newsList: [],
    lastid:0,
    toastHidden:true,
    confirmHidden:true,
    isfrist:1,
    loadHidden:true,
    moreHidden:'none',
    msg:'没有更多文章了'
  },
  loadData: function (lastid){     //点击事件函数
    //显示出加载中的提示
    this.setData({loadHidden:false})

      var limit = 5
      var that = this

      wx.request({
          url: 'http://localhost/weicms/index.php?s=/addon/Cms/Cms/getList',
          data: {lastid:lastid,limit:limit},
          header: {
              'Content-Type': 'application/json'
          },
          success: function(res) {
               if(!res.data){
                    that.setData({ toastHidden:false }) 
                    that.setData({ moreHidden:'none' })
                    return false                
               }
                var len = res.data.length
                var oldLastid = lastid
                that.setData({ lastid: res.data[len-1].id})

                var dataArr = that.data.newsList
                var newData = dataArr.concat(res.data);

                if(oldLastid==0){
                     wx.setStorageSync('CmsList', newData)
                }
                that.setData({ newsList:newData })     //列表循环的数组
                that.setData({ moreHidden:'' })
                console.log('data from url');
          },
          fail: function(res){
                 if(lastid==0){
                     var newData = wx.getStorageSync('CmsList')
                     if(!newData){
                        that.setData({ newsList:newData })
                        that.setData({ moreHidden:'' })

                          var len = newData.length
                          that.setData({ lastid: newData[len-1].id})
                     }
                     console.log('data from cache');
                } else {
                    that.setData({ toastHidden:false, moreHidden:'none', msg:'当前网格异常,请稍后再试' }) 
                }          
          },
          complete: function(){
              //显示出加载中的提示
              that.setData({loadHidden:true})         
          }
      })
  },
  loadMore: function(event){
    var id = event.currentTarget.dataset.lastid
    var isfrist = event.currentTarget.dataset.isfrist
    var that = this

    wx.getNetworkType({
      success: function(res) {
        var networkType = res.networkType // 返回网络类型2g,3g,4g,wifi

        if(networkType!='wifi' && isfrist=='1'){
           that.setData({confirmHidden:false})
        }
      }
    })

    this.setData({isfrist:0})
    this.loadData(id);
  },
  onLoad: function () {
    var that = this

    this.loadData(0);
  },

  toastChange: function(){
    this.setData({toastHidden:true})
  },
  modalChange: function(){
    console.log('abc');
    this.setData({confirmHidden:true})
  }
})

 详情页实例代码:

  

 

 

 

 

 

 

 

 

  

  

  

posted on 2017-06-02 13:38  晨曦年华  阅读(14772)  评论(0编辑  收藏  举报