小程序怎么开发,第一个小程序
1. 啥是小程序?
小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验
微信小程序是一种不需要下载也不需要安装就可以使用的应用程序
它需要所有的开发者都能做到:
- 快速的加载
- 更强大的能力
- 原生的体验
- 易用且安全的微信数据开放
- 高效和简单的开发
2.开发环境
小程序的主要开发语言是 JavaScrip
开发网页时,只需要使用到浏览器,搭配编译器或一些辅助工具即可。
小程序开发,需要申请小程序帐号、登陆微信公众平台、安装小程序开发者工具、配置项目等过程才能完成。
3.新建小程序
3-1扫码进入开发者工具
已注册登陆开发者账号,安装开发者工具(官网可自行下载)后,
每次打开微信开发者工具时,都需要先扫码进入
3-2新建/选择小程序
扫码后,出现如下窗口:
如果之前已建有小程序项目,这里会有记录,如果需要修改或继续开发,选择相应的小程序进入即可;
image.png
如果第一次打开,或者需要新建小程序项目时,点击窗口内的 “+” 加号,会出现一个新建小程序项目的窗口,如下:
image.png
小程序的 AppID 相当于小程序平台的一个身份证,后续你会在很多地方要用到 AppID ,
如果没有AppID,而你的小程序作为测试使用,可以直接使用推荐的测试号即可
如果你要上线发布小程序,就需要购买自己的域名
3-3小程序中的尺寸单位
微信小程序中css的尺寸单位是rpx,rpx可以根据屏幕宽度进行自适应。
规定屏幕宽为750rpx
官方建议以iPhone6 为标准,屏幕宽度为375px,共有750个物理像素,即750rpx = 375px = 750物理像素,
微信小程序也支持尺寸单位rem,
rem和rpx的换算关系:
rem: 规定屏幕宽度为20rem;
1rem = (750/20)rpx
1rpx = 0.5px = 1物理像素
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
}
.userinfo-avatar {
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.userinfo-nickname {
color: #aaa;
}
.userexplain {
margin-top: 200rpx;
}
4.我的第一个小程序
先来看看第一个简单的小程序,就是下面这个熊样子:
image.png
4-1小程序目录结构
- .json 后缀的 JSON 配置文件
- .wxml 后缀的 WXML 模板文件
- .wxss 后缀的 WXSS 样式文件
- .js 后缀的 JS 脚本逻辑文件, 项目入口文件app.js
4-2 json配置文件
在小程序中,json配置文件存放的静态配置的信息。
大眼一扫,不难发现项目的根目录下有一个 app.json 和 project.config.json文件,
在 pages目录的子目录下都有一个.json文件,存放对应页面的配置信息。
app.json 是当前小程序的全局配置,包括小程序的所有页面路径、界面显示、网络超时时间、底部 tab 等等。
app.json文件中配置信息
pages —— 用于描述当前小程序所有页面路径(必填项),这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。
"pages": [
"pages/index/index",//首页
"pages/user/user",//用户页
"pages/logs/logs"//日志页
]
window
—— 定义小程序所有页面的顶部背景颜色,文字颜色定义等等。
想看其他配置,请移步官方大厅 小程序配置app.json
"window": {
"backgroundTextStyle": "light",//下拉背景样式,loading图的样式,dark或light
"navigationBarBackgroundColor": "#ABE7F4",//导航栏背景颜色
"navigationBarTitleText": "测试小程序",//导航栏标题名字
"navigationBarTextStyle": "black" //导航栏标题颜色,black或white
}
tabBar——小程序底部导航栏及tab切换时对应的页面
"tabBar": {
//tab列表,最少两个,最多五个,里面存放对象,每个对象接收四个参数,如下
"list": [
{
"pagePath": "pages/index/index",//跳转页面
"text": "首页",//标题名字
"iconPath":"/ico/home.png",//图片路径
"selectedIconPath":"/ico/home-active.png"//选中点击后的图片路径
},
{
"pagePath": "pages/user/user",
"text": "用户",
"iconPath":"/ico/user.png",
"selectedIconPath":"/ico/user-active.png"
},
{
"pagePath": "pages/logs/logs",
"text": "日志",
"iconPath":"/ico/log.png",
"selectedIconPath":"/ico/log-active.png"
}
],
"backgroundColor": "#C8F7D3" //底部导航栏背景色
}
sitemapLocation 来指明 sitemap.json 的位置
"sitemapLocation": "sitemap.json"
sitemap.json
小程序根目录下的 sitemap.json 文件用来配置小程序及其页面是否允许被微信索引。
默认情况下,所有页面都会被索引。
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
配置 path/to/page 页面不被索引,其余页面允许被索引
{
"rules":[{
"action": "disallow",
"page": "path/to/page"
}]
}
project.config.json
小程序开发者工具在每个项目的根目录都会生成一个 project.config.json文件,
在工具上做的任何配置都会写入到这个文件,当重新安装工具或者换电脑工作时,只要载入同一个项目的代码包,开发者工具就自动会帮你恢复到当时你开发项目时的个性化配置,其中会包括编辑器的颜色、代码上传时自动压缩等等一系列选项。
{
"description": "项目配置文件",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": true,
"es6": true,
"enhance": false,
"postcss": true,
"minified": true,
"newFeature": true,
"coverView": true,
"nodeModules": false,
"autoAudits": false,
"showShadowRootInWxmlPanel": true,
"scopeDataCheck": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"compileType": "miniprogram",
"libVersion": "2.0.4",
"appid": "wx933fdd3711986c86",
"projectname": "ExeciseNotebook",
"debugOptions": {
"hidedInDevtools": []
},
"isGameTourist": false,
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"currentL": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
5-1 框架
整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。
小程序提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,
并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
5-2 数据绑定
框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。
当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
在一个组件的属性上添加bindtap属性并赋予一个值(一个函数名)
当点击该组件时, 会触发相应的函数执行(通过bindtap绑定点击事件)
pages/index/index.wxml
<view class="container">
<view class="userinfo">
<!--wx:if wx:else 条件渲染-->
<button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
<block wx:else>
<!-- 头像 -->
<!--绑定点击事件-->
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover">
</image>
<!-- 昵称 -->
<text class="userinfo-nickname">
<!--数据绑定-->
{{userInfo.nickName}}
</text>
</block>
</view>
<view class="userexplain">
<text class="user-motto">{{explain}}</text>
</view>
</view>
pages/index/index.js
//获取应用实例
const app = getApp();
Page({
data: {
explain:'hello,this is my first file',
userInfo: {},
hasUserInfo: false,
//判断小程序的API,回调,参数,组件等是否在当前版本可用。
canIUse: wx.canIUse('button.open-type.getUserInfo')
},
//点击事件处理函数
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
} else if (this.data.canIUse){
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
app.userInfoReadyCallback = res => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
} else {
// 在没有 open-type=getUserInfo 版本的兼容处理
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}
},
getUserInfo: function(e) {
console.log(e)
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
})
pages/logs/logs.wxml
<view class="container log-list">
<!--列表渲染-->
<block wx:for="{{logs}}" wx:for-item="log">
<text class="log-item">
{{index + 1}}. {{log}}
</text>
</block>
</view>
pages/logs/logs.js
const util = require('../../utils/util.js');
Page({
/*页面的初始数据*/
data: {
logs:[]
},
/*生命周期函数--监听页面加载*/
onLoad: function (options) {
this.setData({
logs: (wx.getStorageSync('logs') || []).map(log => {
return util.formatTime(new Date(log))
})
})
},
/*生命周期函数--监听页面初次渲染完成*/
onReady: function () {
},
/**生命周期函数--监听页面显示*/
onShow: function () {
},
/**生命周期函数--监听页面隐藏*/
onHide: function () {
},
/*生命周期函数--监听页面卸载*/
onUnload: function () {
},
/*页面相关事件处理函数--监听用户下拉动作*/
onPullDownRefresh: function () {
},
/*页面上拉触底事件的处理函数*/
onReachBottom: function () {
},
/*用户点击右上角分享*/
onShareAppMessage: function () {
}
})
utils/util.js
const formatTime = date => {
const year = date.getFullYear(); // 年
const month = date.getMonth() + 1; // 月
const day = date.getDate(); // 日
const hour = date.getHours(); // 时
const minute = date.getMinutes(); // 分
const second = date.getSeconds(); // 秒
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':');
}
const formatNumber = n => {
n = n.toString();
return n[1] ? n : '0' + n;
}
module.exports = {
formatTime: formatTime
转载自:此鱼非闲鱼也
网友评论