小程序学习:电影周周看

第二讲 初识小程序

2.1 第一个实战项目:电影周周看V1

2.2 创建项目和目录文件结构

小程序包含一个描述整体的APP和多个描述各页面的page

一个小程序主体部分由三个文件组成,必须放在项目的根目录,如下:

默认工程文件:project.config.json

  1. .json 后缀的 JSON 配置文件
  2. .wxml 后缀的 WXML 模板文件
  3. .wxss 后缀的 WXSS 样式文件
  4. .js 后缀的 JS 脚本逻辑文件

js

json

{

"pages":["pages/about/about" ]

}

wxml

wxss

 

pages/about

js

page({})

json

wxml

<text claass="info">hello word </text>

wxss

.info{

font-weight:bold;

font-size:30px;

}

2.3 页面配置初探

index.json:

{
  "navigationBarTitleText": "首页",
  "navigationBarBackgroundColor": "#fff",
  "navigationBarTextStyle": "black"
}

2.4 VIEW、TEXT、IMAGE组件

class

id

style

bindtap="f0"//函数

hidden="true"//是否隐藏

data-user-name="user"//自定义属性

index.wxml

<view>
    <image src="\pages\images\u0.jpg"></image>
    <text>电影周周看</text>
    <text>我每周推荐一部好片</text>
    <text>我的微博:@星空风月</text>
</view>

2.5 快速实现基本布局

vr:viewport height

1、普通布局:

about.wxml

<view class="container">
  <image src="/pages/images/u0.jpg"></image>
  <text>电影周周看</text>
  <text>我每周推荐一部好片</text>
  <text>我的微博:weibo.com/@星空风月</text>
</view>

about.wxss

.container{
  background-color: #eee;
  height: 100vh;
  text-align: center;
}
text{
  display: block;/*显示为块级元素*/
}
image,text{
  margin-bottom: 50px;
}

2、应用弹性盒子布局

优点:比较统一、方式灵活

.container{
  background-color: #eee;
  height: 100vh;
  display: flex;/*变为flex container 元素从左往右*/
  flex-direction: column;/*改为垂直从上往下*/
  justify-content: space-around;/*在主轴方向上的聚集和分布方式*/
  align-items: center;/*居中*/
}

2.6 让元素大小适配不同宽度屏幕

小程序规定所有设备的屏幕宽高为:750rpx

iPhone6屏幕:

px:rpx    比例为     1:2

 

/* 头像图片 */
.about_img{
  width: 375rpx;
  height: 375rpx; 
  border-radius: 50%;
}
/* 电影周周看 */
#about_zzk{
  font-weight: bold;
  font-size: 60rpx;
}

vh 说明:

相对于视口的高度。视口被均分为100单位的vh

示例代码:

h1 {
	font-size: 8vh;
}

如果视口的高度是200mm,那么上述代码中h1元素的字号将为16mm,即(8x200)/100

2.7 新增“每周推荐”WEEKLY页并快速调试

每一个用户可能访问到的页面,都需要在前局配置中来登记他的访问路径。

weekly.js:调用page配置函数,来给页面注册一个空对象  Page({})

weekly.json:使用  { } 创建空的json对象配置文本  

weekly.wxml:

<view class="container">
  <text id="about_zzk">本周推荐</text>
  <image class="about_img" src="/pages/images/handou.jpg"></image>
  <text>憨豆先生</text>
  <text>点评:最精彩的剧本是最真实的黑帮电影</text>
</view>

weekly.wxss:

.container{
  background-color: #eee;
  height: 100vh;
  display: flex;/*变为flex container 元素从左往右*/
  flex-direction: column;/*改为垂直从上往下*/
  justify-content: space-around;/*在主轴方向上的聚集和分布方式*/
  align-items: center;/*居中*/
}

2.8 使用NAVIGATOR组件-从ABOUT页跳转到WEEKLY页

display: black  块状元素

display: inline  

open-type="redirect"不可返回

open-type="navigate"  默认可返回

open-type="redirect" 不可返回

about.wxml

<view class="container">
  <image class="about_img" src="/pages/images/u0.jpg"></image>
  <text id="about_zzk">电影周周看</text>
  <view>
  <text>我</text><navigator url="/pages/weekly/weekly" style='display:inline' open-type="navigate" hover-class="nav-hover" class="nav-default">每周推荐</navigator><text>一部好片</text
  >
  </view>
  <text>我的微博:weibo.com/@星空风月</text>
</view>

about.wxss

.container{
  background-color: #eee;
  height: 100vh;
  display: flex;/*变为flex container 元素从左往右*/
  flex-direction: column;/*改为垂直从上往下*/
  justify-content: space-around;/*在主轴方向上的聚集和分布方式*/
  align-items: center;/*居中*/
}
/* 头像图片 */
.about_img{
  width: 375rpx;
  height: 375rpx; 
  border-radius: 50%;
}
/* 电影周周看 */
#about_zzk{
  font-weight: bold;
  font-size: 60rpx;
}
/* 默认蓝色放在前 */
.nav-default{
  color: blue;
}
/* 点击后的红色放在后面 */
.nav-hover{
  color: red;
}

2.9 配置TABBAR-对若干一级页面的入口链接

<navigator>元素点击无效,设置

open-type=“switchTab”跳转并改变tabBar图标跳转

app.json中使用tabBar属性

{
  "pages": [
    "pages/about/about",
    "pages/weekly/weekly"
  ],
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/weekly/weekly",
        "text": "每周推荐",
        "iconPath": "pages/images/icons/weekly.png",
        "selectedIconPath": "pages/images/icons/weekly-selected.png"
      },
      {
        "pagePath": "pages/about/about",
        "text": "关于",
        "iconPath": "pages/images/icons/about.png",
        "selectedIconPath": "pages/images/icons/about-selected.png"
      }
    ],
    "color": "#000000",
    "selectedColor": "#00f"
  }
}

"color": "#000000",

"selectedColor": "#00f"

2.10 配置全局的导航栏样式

顶部导航栏样式默认使用黑底白字

代码直接复制的方法必然会带来代码升级时候的问题

app.json中使用Windows属性

  "window": {
    "navigationBarBackgroundColor": "#ffffff",
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "电影周周看",
    "backgroundColor": "#eeeeee",
    "backgroundTextStyle": "light",
    "enablePullDownRefresh": false
  }

第三讲 电影周周看v2

3.1 数据绑定

一般方法通过ajax调用server的数据

 weekly.js 里面添加数据变量:

Page({
  data: {
    thisWeekMoview: [
      {
        name: "教父",
        comment: "最精彩的剧本,最真实的黑帮电影。",
        imagePath: "/images/jf.jpg"
      }
    ],
    count: 123
  }
})

weekly.wxml页面

<view class="container">
  <text id="about_zzk">本周推荐</text>
  <image class="about_img" src="{{thisWeekMovie.imagePath}}"></image>
  <text>{{thisWeekMovie.name}}</text>
  <text>点评:{{thisWeekMovie.comment}}</text>
</view>

3.2 小程序运行环境与基本架构 VIDEO

在小程序调试窗口里面的 AppData,可以对页面里的数据进行调试。我们可以看到,小程序给页面 weekly 添加了一个变量 webviewId 等于10。这个是做什么用的呢?

这就需要了解小程序的运行环境和运行架构。

运行环境: 每个小程序都是运行在它所在的微信客户端上的,通过微信客户端给它提供运行环境,小程序可以直接获取微信客户端的原生体验和原生能力。

视力层和逻辑层: 小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端做中转,逻辑层发送网络请求也经由Native转发,小程序的通信模型下图所示。

所以,刚才我们在 AppData 中可以看到,about页和weekly页都内置了一个 webviewId 的内部状态变量,记录它们各自是在几号 webview 进程中进行渲染的。

3.3 条件渲染

条件渲染指的是:条件成立时才渲染生成。
拿上面的例子来看,我们给推荐页面的电影添加一个这段,表明这个电影是不是强烈推荐的。

isHighlyRecommended: true

我们现在要做的一个改动就是,希望在视图中,对于真正想强烈推荐的电影,我们要显示一个强烈推荐的红色标记。

首先我们把强烈推荐的元素定义出来,添加到 weekly.wxml 中:

<text style="font-size:16px; color:red;"> 强烈推荐 </text>

这时可以看到,在视图中,出现了红色的 “强烈推荐” 的字样。

但是这个是肯定会生成的,但我们需要的效果是,如果电影是要推荐的,就生成;不是推荐的,就不生成。

所以,我们就可能 通过 wx:if 做条件判断来实现。代码可以修改为:

<text wx:if="{{thisWeekMovie.isHighlyRecommended}}" style="font-size:16px; color:red;">强烈推荐</text>

这个意思是,强烈推荐这个 text 元素,渲梁生成的条件是:绑定到了 thisWeekMoview 的 isHighlyRecommended 属性上。当这个属性是 true 的情况下,这个 text 元素会被生成,如果这个属性是 false 的情况下,这个 text 元素就不会生成。

同时,我们也可以使用 hidden 属性来实现这个效果。 代码如下:

<text hidden="{{!thisWeekMovie.isHighlyRecommended}}" style="font-size:16px; color:red;">强烈推荐</text>

这里注意是求反的操作。当用户没有推荐的时候,hidden是true;用户强烈推荐的时候,hidden是false,所以是求反的操作。

此时,我们在 AppData 里面进行查看,可以看到,这个 text 元素无论 hidden 是取 true 还是 false,都始终是生成的。因此,我们可以知道,使用 hidden 属性时,这个元素总是要被渲染生成的,hidden 只是控制了其可见性而已。

那么,在实际应用中,我们该如何选择呢?
从上面的例子我们可以看到,当wx:if的条件值切换时,框架有一个局部渲染的过程,他会确保条件在切换是销毁或者重新渲染。同时wx:if也是有惰性的,如果初始渲染条件为false,框架什么也不会做,只有在条件第一次变为真的时候才会开始渲染。因此,对于可见性需要频繁切换的时候,不建议使用条件渲染,因为它的开销会比较大,这个时候就使用 hidden

对于我们的这个例子,我们要如何选择呢? 当电影列表从服务器获得以后,用户就不会对是否推荐的信息进行修改。意思就是,强烈推荐这个元素的渲染条件,用户是不会去发生切换的。所以这个时候,我们应该使用 条件渲染来做 这件事情。这个时候如果使用 hidden,他的初始化开销会增大。博主没有去推荐这个电影,它也会在初始生成的时候,去生成这么一个元素。

3.4 列表渲染

原来的weekly.wxss

.container{
  background-color: #eee;
  height: 100vh;
  display: flex;/*变为flex container 元素从左往右*/
  flex-direction: column;/*改为垂直从上往下*/
  justify-content: space-around;/*在主轴方向上的聚集和分布方式*/
  align-items: center;/*居中*/
}

原来的weekly.wxml

<view class="container">
  <text id="about_zzk">本周推荐</text>
  <image class="about_img" src="{{thisWeekMovie.imagePath}}"></image>
  <text>{{thisWeekMovie.name}}</text>
  <text>点评:{{thisWeekMovie.comment}}</text>
  <text hidden="{{!thisWeekMovie.isHighlyRecommended}}" style="font-size:32rpx;color:red;">※ 强烈推荐</text>
</view>

现在的:

weekly.wxss

.movie{
  display: flex;
}
.movie-details{
  display: flex;
  flex-direction: column;
  width: 550rpx;
}
.movie-image{
  width: 200rpx;
  height: 200rpx;
}

weekly.wxml

<view>
  <view class="movie" wx:for="{{WeeklyMovieList}}">
    <image class="movie-image" src="{{item.imagePath}}"></image>
    <view class="movie-details">
      <text>第{{index+1}}周:{{item.name}}</text>
      <text>点评:{{item.comment}}</text>
      <text hidden="{{!item.isHighlyRecommended}}" style="font-size:32rpx;color:red;">※ 强烈推荐</text>
    </view>
  </view>
</view>

weekly.js

Page({
  data: {
    WeeklyMovieList:[
      {
        name: "泰坦尼克号",
        comment: "失去的才是永恒的",
        imagePath: "/images/titanic.jpg",
        isHighlyRecommended: false,
      },
      {
        name: "这个杀手不太冷",
        comment: "小萝莉与怪蜀黍纯真灿烂的爱情故事",
        imagePath: "/images/leon.jpg",
        isHighlyRecommended: false,
      },
      {
        name: "教父",
        comment: "最精彩的剧本,最真实的黑帮电影。",
        imagePath: "/images/jf.jpg",
        isHighlyRecommended: true,
      }
    ]
  }
})

3.5 使用SWIPER组件

weiper元素默认:150像素高,image元素默认:240元素高

sweiper元素设置的宽高weiper-item百分百比例显示

indicator-dots="ture" 属性显示面板指示

3.6 页面的生命周期函数

需求1:

对于 swiper ,要设置默认显示的那页幻灯片,可以添加一个 current 属性,这个属性默认值是0。也就是说,首张幻灯片页是默认显示的。现在要做的是,因为用户每次最想看到的是,本周推荐的页。所以,要把 swiper 默认设置成最后一页幻灯片。

最后一页的序号是 数组长度减1。解决方案是,把 current 属性这样绑定:

current = '{{weeklyMovieList.length-1}}'

需求2:

  • 进而会引出 onLoad 生命周期函数,可以查看如何对元素进行初始化;
  • 介绍 onShow, onReady, onHide, onUnload 生命周期函数。

bindtap绑定事件处理函数f0

<text bindtap='f0' wx:if='{{index < (weeklyMovieList.length - 1)}}' class='return-button'>返回本周</text>
<text bindtap='f0' wx:if='{{index < (weeklyMovieList.length - 1)}}' class='return-button'>返回本周</text>
 onLoad: function (options) {
    this.setData({
      currentIndex: this.data.weeklyMovieList.length - 1
    })
  },

onload,事件会在页面或图像加载完成后立即发生。

onShow, 当页面每一次显示,都要调一次,每一次页面从隐藏到可见,都会调用

onReady, 等页面渲染完成,全部好了,已经可以交互的时候被调用一次

onHide, 当页面每次隐藏的时候调用一次

onUnload,当页面被关闭或卸载的时候调用

 

position:relative;相对定位

position:absolute;相对定位

3.7 更新数据

在这里,展示了一种数据更新的方式,就是直接像下面函数的形式来进行更新:

f0: function(event){
    this.data.count = this.data.count + 1
}

反复点击按钮,会发现页面显示并没有更新。但是进入 AppData 查看,可以发现 count 的值已经更新到了 9。

所以,这种通过对变量直接赋值写入的方式,不能让框架自动更新,而且,非常容易引起数据不一致问题。所以,对小程序中的变量进行更新,不能采取直接赋值的方式,而必须采用小程序提供的 this.setData 方法。

发现实际的写法为:

  f0: function (event) {
    this.setData({
      currentIndex: this.data.weeklyMovieList.length - 1
    })
  }

3.8 事件机制

前面的应用里,我们已经使用了事件函数。这一节我们要讲解如下事项:

  • 事件绑定
  • 冒泡事件与非冒泡事项
  • bind 绑定 VS catch 绑定
  • 事件对象简介
  • 对于点击的操作有两种处理方式:
<button catchtap='f0'> +1 </button>
<button bindtap='f0'> +1 </button>


这两种有什么区别呢?首先我们要了解冒泡事件和非冒泡事件。小程序中事件分为冒泡事件和非冒泡事件:

  • 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
  • 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
  • 在小程序事件系统文档中,给出了哪些是冒泡事件。

对于 bindtap ,如果事件触发了,就会向上传递给父元素。也就是说,button 如果点击了,就会传递给外边的 view 元素,如果 view 元素里面自己也有一个 bindtap 函数,它也会调用这个函数进行处理。

相反,如果这里使用 catchtap ,那么点击以后,就会阻止元素向上传递。也就是说,按钮点击以后,只会处理自己的函数,但外层的 view 元素,就不会进行相应处理。

接着,我们看看事件对象包含哪些信息。我们把f0函数修改如下:

f0: function(event){
   console.log(event)
}

点击以后,可以在 log 里看到如下事件触发后,方方面面的信息,具体如下:
在这里插入图片描述
比如说事件的类型,是一个 tap 事件,还有一个是 currentTarget ,指向的是当前事件处理的元素。可以观察到,currentTarget 还有一个 dataset 属性,这个还会在后边讲到。

第四讲 电影周周看v3

4.1 组件的自定义数据属性

继续完善电影周周看微信小程序,

  • 需求:从weekly 页面上的电影卡片跳转到电影详情页,因此,要新增 detail页面
  • 使用 wx.navigateTo()
  • 参数化的 page path
  • 组件的自定义数据属性:向逻辑层的业务数据传递

首先,新建details页面,这里给出 detail页的基本代码:
details.wxml

<text>detail page</text>

detail.json

{
    "navigationBarTitleText": "电影详情页"
}

detail.js

Page({})

然后,在weekly.wxml中,每一个电影,都对应了一个卡片,我们找到它所在的view,需要给它一个点击函数,然后我们在weekly.wxml新增代码:

这样就绑定了tab事件处理函数,同进,在weekly.js里面添加事件处理函数:

从代码中可以看到,在f1中,实现了页面的跳转,使用的是wx.navgigateTo 函数。这个函数的功能是保留当前页面,中转到应用内的某个页面,同时,使用 wx.navigateBack 函数可以返回原页面。

同时,微信还提供了其它几个方式,比如,wx.redirectTo 是关闭当前页面,跳转到应用中的某个页面(注意:使用的过程中,当前的页面是会关闭的)。类似的还有 wx.switchTab ,是跳转到 tabBar 页面,并关闭当前所有非 tabBar 页面。

现在可以看一下效果,当点击一个电影元素,就跳转一下面的 detail 页:

同时,可以注意到,每次点击一个电影卡片,我们希望得到的详情是不一样的。那么如何实现这一功能呢?这样,我们给每一个电影的信息里,添加一个元素 id,如下所示:

每个电影的 id 是不一样的,同进,在视图层 weekly.wxml 中添加代码,把电影的 id 显示出来,如下图所示:

那么问题来了,如何把 view 元素中的取值,传递给逻辑层呢?
为详细说明这一操作,我们给 weekly.wxml 添加下面代码:

然后,在逻辑层 weekly.js 添加下面的代码:

接着,运行小程序,点击电影卡片,可以看到控制台有下面的输出:
1291841
blabla
这说明什么呢?当视图层的 view 触发一个事件的时候,它封装了一些数据,这些关键数据,实际上是抽取的,形式为 " data-" 开头,声明的自定义的一些用户数据。
比如说,data-user-name,到逻辑层就变为了:event.currentTarget.dataset.userName的格式
data-movie-id,到逻辑层就变成了:event.currentTarget.dataset.movieId 的格式。
这样,就要可以方便的把电影的 id 传递给 navigateTo 函数,如下所示:

4.2 电影详情页的基本框架

4.3 发起请求API

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-09-17 01:30  明金同学  阅读(141)  评论(0编辑  收藏  举报