Mini Program Project Learning--**Chapter 3: WXSS-WXML-WXS Syntax**Event Processing-Component Development

Chapter 3: WXSS-WXML-WXS syntax event processing-component development

image-20230118142752892

01_(Master) WXML syntax-basic rules and mustache syntax

image-20230118192943387

Page({
    
    
  data: {
    
    
    message: "Hello World",
    firstname: "kobe",
    lastname: "bryant",
    date: new Date().toLocaleDateString(),
  },
})  

<!-- 1.Mustache语法 -->
<view>{
    
    {
    
     message }}</view>
<view>{
    
    {
    
     firstname + " " + lastname }}</view>
<view>{
    
    {
    
     date }}</view>

02_(Master) WXML syntax-logical conditional judgment-instructions

image-20230118193941695

  score: 10,
      
  <!-- 2.条件判断 为false的情况下是直接不渲染元素 -->
<view wx:if="{
    
    {score > 90}}">优秀</view>
<view wx:elif="{
    
    {score > 80}}">良好</view>
<view wx:elif="{
    
    {score >= 60}}">及格</view>
<view wx:else>不及格</view>
    

03_(Master) WXML syntax-the difference between hidden attribute and if

image-20230118201109122

 isHidden: false,
     
 onChangeTap() {
    
    
    this.setData({
    
    
      isHidden: !this.data.isHidden
    })
  }

<!-- 3.hidden属性:v-show 实现原理 display:none -->
<!-- 基本使用 -->
<view hidden>我是hidden的view</view>

<!-- 切换案例 -->
<button bindtap="onChangeTap">切换</button>
<!-- 频繁更新的时候用hidden -->
<view hidden="{
    
    {isHidden}}">哈哈哈哈</view>
<!-- dom树中已经不存在 ,但是小程序可能因为热更新的问题导致 我们看代码的时候并没有移除,但本质上已经移除了 -->
<view wx:if="{
    
    {!isHidden}}">呵呵呵呵</view>

04_(Master) WXML syntax-list rendering-for basic use

image-20230118203007924

There are two common ways to write wx:key

Writing method one: wx:key="*this" represents the item itself. If the item itself is an object type, the object type bound to the key will be converted into a string [Object object], so the key is no longer unique. Not recommended when using

Writing method 2: Write the string directly - for example wx:key="id", then the id will be automatically found from the item and the id attribute will be used as the key

 books: [
      {
    
     id: 111, name: "代码大全", price: 98 },
      {
    
     id: 112, name: "你不知道JS", price: 87 },
      {
    
     id: 113, name: "JS高级设计", price: 76 },
    ]
<!-- 4.列表展示 -->
<!-- 4.1.wx:for基本使用 -->
<!-- 遍历data中的数组 -->
<view class="books">
  <view wx:for="{
    
    {books}}" wx:key="id">
    <!-- item: 每项内容, index: 每项索引 -->
    {
    
    {
    
    item.name}}-{
    
    {
    
    item.price}}
  </view>
</view>
<!-- 遍历数字 -->
<view class="number">
  <view wx:for="{
    
    {10}}" wx:key="*this">
    {
    
    {
    
     item }}
  </view>
</view>
<!-- 遍历字符串 -->
<view class="str">
  <view wx:for="coderwhy" wx:key="*this">
    {
    
    {
    
     item }}
  </view>
</view>

05_(Master) WXML syntax-list rendering-for details supplement

image-20230118204654057

image-20230118204700457

image-20230118204711405

By default, the item-index name is fixed **

item refers to each item traversed, index refers to the index

We can specify the name of item** via wx:for-item="book" and index wx:for-index="i"

<!-- 4.2. 细节补充: block-item/index名称-key的使用 -->
<view class="books">
  <block wx:for="{
    
    {books}}" wx:key="id" wx:for-item="book" wx:for-index="i">
    <view>{
    
    {
    
     book.name }}-{
    
    {
    
     book.price }}-{
    
    {
    
     i }}</view>
  </block>
</view>

06_(Understanding) WXS syntax-Introduction and underlying implementation of WXS

image-20230118210238690

image-20230118205923105

**WXS (WeiXin Script)** is a script language for small programs. Combined with WXML, the structure of the page can be constructed

Why design the WXS language?

In WXML, functions defined in Page/Component cannot be called directly. Because of the dual-thread model

Due to differences in operating environments, WXS in mini programs on iOS devices will be 2 to 20 times faster than JavaScript code. There is no difference in operating efficiency between the two on Android devices (because the underlying implementation is different);

07_(Master) WXS-WXS two writing methods and case exercises

[The external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-XKXn4fre-1675304560085) (null)]

es6 code is not allowed to be placed in wxs, only es5 code can be placed

1. Method 1: Label

There are two prerequisites for defining wxs: 1. There must be a correspondingly named module, and 2. It must be exported before it can be called from other places.

When using wxs, you must specify the corresponding wxs module.

<!-- wxs里面不允许放es6代码,只能放es5代码 -->
<!-- 使用wxs的两个前提,1.必须有对应命名的module,2.必须导出后, 才能被其他地方调用 -->
<!-- 1.方式一: 标签 -->
<wxs module="format">
  
  function formatPrice(price) {
    
    
    return "¥" + price
  }

  // 必须导出后, 才能被其他地方调用: 必须使用CommonJS导出
  module.exports = {
    
    
    formatPrice: formatPrice
  }
</wxs>

<view class="books">
  <block wx:for="{
    
    {books}}" wx:key="id">
    <!-- 使用wxs,必须指定对应的wxs的模块 -->
    <view>name:{
    
    {
    
    item.name}}-price:{
    
    {
    
    format.formatPrice(item.price)}}</view>
  </block>
</view>

2. Method 2: independent file, introduced through src – commonly used in development

<wxs module="format" src="/utils/format.wxs"></wxs>

<view class="books">
  <block wx:for="{
    
    {books}}" wx:key="id">
    <!-- 使用wxs,必须指定对应的wxs的模块 -->
    <view>name:{
    
    {
    
    item.name}}-price:{
    
    {
    
    format.formatPrice(item.price)}}</view>
  </block>
</view>

<view class="total">总价格: {
    
    {
    
    format.calcPrice(books)}}</view>

format.wxs

function formatPrice(price) {
    
    
  return "¥" + price
}

function calcPrice(books) {
    
    
  return "¥" + books.reduce(function(preValue, item) {
    
    
    return preValue + item.price
  }, 0)
}

// 对count进行格式化
function formatCount(count) {
    
    
  count = Number(count)
  if (count >= 100000000) {
    
    
    return (count / 100000000).toFixed(1) + "亿"
  } else if (count >= 10000) {
    
    
    return (count / 10000).toFixed(1) + "万"
  } else {
    
    
    return count
  }
}

// function padLeft(time) {
    
    
//   if ((time + "").length >= 2) return time
//   return "0" + time
// }

// 2 -> 02
// 24 -> 24
function padLeft(time) {
    
    
  time = time + ""
  return ("00" + time).slice(time.length)
}

// 对time进行格式化
// 100 -> 01:40
function formatTime(time) {
    
    
  // 1.获取时间
  var minute = Math.floor(time / 60)
  var second = Math.floor(time) % 60

  // 2.拼接字符串
  return padLeft(minute) + ":" + padLeft(second)
}

// 必须导出后, 才能被其他地方调用: 必须使用CommonJS导出
module.exports = {
    
    
  formatPrice: formatPrice,
  calcPrice: calcPrice,
  formatCount: formatCount,
  formatTime: formatTime
}

08_(Master) WXS syntax-WXS case exercise-count formatting

image-20230118214739635

<wxs module="format" src="/utils/format.wxs"></wxs>
<view>------------题目练习------------</view>
<view class="count">播放量: {
    
    {
    
    format.formatCount(playCount)}}</view>

// 对count进行格式化
function formatCount(count) {
    
    
 // 使用Number()方法不能定义变量,不然就var count = parseInt(count)
  count = Number(count)
  if (count >= 100000000) {
    
    
    return (count / 100000000).toFixed(1) + "亿"
  } else if (count >= 10000) {
    
    
    return (count / 10000).toFixed(1) + "万"
  } else {
    
    
    return count
  }
}

09_(Master) WXS syntax-WXS case practice-time formatting

image-20230118220756508

The class attribute cannot be added to the block tag

  duration: 255,
 currentTime: 65

<wxs module="format" src="/utils/format.wxs"></wxs>

<view class="time">
  {
    
    {
    
    format.formatTime(currentTime)}}/{
    
    {
    
    format.formatTime(duration)}}
</view>

format.wxs
// 时间格式的转换方式一
// function padLeft(time) {
    
    
//   if ((time + "").length >= 2) return time
//   return "0" + time
// }
// 时间格式的转换方式二
// 2 -> 02
// 24 -> 24
function padLeft(time) {
    
    
  time = time + ""
  return ("00" + time).slice(time.length)
}

// 对time进行格式化
// 100 -> 01:40
function formatTime(time) {
    
    
  // 1.获取时间
  var minute = Math.floor(time / 60)
  var second = Math.floor(time) % 60

  // 2.拼接字符串
  return padLeft(minute) + ":" + padLeft(second)
}

// 必须导出后, 才能被其他地方调用: 必须使用CommonJS导出
module.exports = {
    
    
  formatPrice: formatPrice,
  calcPrice: calcPrice,
  formatCount: formatCount,
  formatTime: formatTime
}

Chapter 3: Event processing of small programs

image-20230118221512892

10_(Master) Event Processing-Introduction to Events-Basic Usage-Event Types

image-20230118222610608

image-20230118222619644

<!-- 1.事件的基本使用 -->
<button bindtap="onBtnTap">按钮</button>

// 绑定事件监听函数
  onBtnTap(event) {
    
    
    console.log("onBtnTap:", event);
  },

11_(Master) event processing-target difference in event object

image-20230118223608669

[The external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-3w2YQyfU-1675304560043) (null)]

1. target element that triggers the event
2. currentTarget element that handles the event

<!-- 2.event中target和currentTarget区别 -->
<view id="outer" class="outer" data-name="why" bindtap="onOuterViewTap">
  <view id="inner" class="inner"></view>
</view>


onOuterViewTap(event) {
    
    
    // 1.target触发事件的元素
    // 2.currentTarget处理事件的元素
    console.log("onOuterViewTap:", event);
    console.log(event.target);
    console.log(event.currentTarget);
    // 虽然是false,但是里面的属性是一模一样的,相当与new两个对象,内存地址不同,但是里面完全相同
    // console.log(event.target== event.currentTarget);

    // 3.获取自定义属性: name  ---用currentTarget获取处理事件的元素 自定义属性
    const name = event.currentTarget.dataset.name
    console.log(name);
  },

12_(Understand) event processing-the difference between event object touches

image-20230118224657338

Difference one:

touches All fingers that are touching, if leaving touches is empty

changedTouches The latest touch of all fingers (element that sends changes) is also counted if they leave (if changes are sent to leave, changedTouches is the value of leaving)

 <!-- 3.event中touches和changeTouches区别 -->
<view
  class="touches"
  bindtap="onTouchTap"
  bindlongpress="onLongPress"
  bindtouchend="onTouchEnd"
>
  多指触摸
</view>

// 监听触摸事件
  onTouchTap(event) {
    
    
    console.log("tap:", event);
  },
  onLongPress(event) {
    
    
    console.log("long:", event);
  },
  onTouchEnd(event) {
    
    
    console.log("end:", event);
  },

13_(Master) Event Processing-Parameter Passing-Custom Attributes

image-20230119090632116

Pass the data of the view layer into the logical layer – through the custom attribute data- (custom attribute name)

<!-- 4.event的参数传递 -->
<view 
  class="arguments"
  bindtap="onArgumentsTap"
  data-name="why"
  data-age="18"
  data-height="1.88"
>
  参数传递
</view>

// 监听事件, 并且传递参数
  onArgumentsTap(event) {
    
    
    console.log("onArgumentsTap:", event);
    const {
    
     name, age, height } = event.currentTarget.dataset
    console.log(name, age, height);
  },

14_(Master) Event Processing-Case Exercise of Parameter Passing

image-20230119101636704

// Event.target cannot be used here because the outer layer of wxml includes text, and there is no index on text. undefined

// 1.The target element that triggers the event is this 2.currentTarget elements that handle events

pit

1. When adding attributes, there cannot be spaces in front of the attribute values.

<!-- 5.tab-control案例(重要) -->
<view class="tab-control">
  <block wx:for="{
    
    {titles}}" wx:key="*this">
    <view class="item {
    
    {index === currentIndex ? 'active': ''}}" 
    bindtap="onItemTap" 
    data-index="{
    
    {index}}">
      <text class="title">{
    
    {
    
    item}}</text>
    </view>
  </block>
</view>

  data: {
    
    
    titles: ["手机", "电脑", "iPad", "相机"],
    currentIndex: 0
  },
  // 导航栏切换事件
  onItemTap(event){
    
    
    const currentIndex = event.currentTarget.dataset.index
    this.setData({
    
    
      currentIndex
    })
  }

15_(Understand) event processing-event capture and bubbling stages

image-20230119104316275

When there is a nested relationship between elements, event capture and bubbling will occur.

capture-bind:tap (capture-bindtap) belongs to the capture phase, and bind:tap (bindtap) belongs to the bubbling phase – they both capture from the outside to the inside, and then bubble from the inside to the outside.

image-20230119103702656

<!-- 6.捕获和冒泡阶段 -->
<view class="view1" capture-bind:tap="onView1CaptureTap" bindtap="onView1Tap">
  <view class="view2" capture-bind:tap="onView2CaptureTap" bindtap="onView2Tap">
    <view class="view3" capture-bind:tap="onView3CaptureTap" bindtap="onView3Tap"></view>
  </view>
</view>

// 捕获和冒泡过程
  onView1CaptureTap() {
    
    
    console.log("onView1CaptureTap");
  },
  onView2CaptureTap() {
    
    
    console.log("onView2CaptureTap");
  },
  onView3CaptureTap() {
    
    
    console.log("onView3CaptureTap");
  },
  onView1Tap() {
    
    
    console.log("onView1Tap");
  },
  onView2Tap() {
    
    
    console.log("onView2Tap");
  },
  onView3Tap() {
    
    
    console.log("onView3Tap");
  },

7. Replace bind with catch: prevent events from being delivered in only one step (understand)

catch will further prevent event delivery. When encountering capture-catch:tap, events will not be passed down (it is rarely used, just understand it)

<!-- 6.捕获和冒泡阶段 -->
<view class="view1" capture-bind:tap="onView1CaptureTap" bindtap="onView1Tap">
  <view class="view2" capture-catch:tap="onView2CaptureTap" bindtap="onView2Tap">
    <view class="view3" capture-bind:tap="onView3CaptureTap" bindtap="onView3Tap"></view>
  </view>
</view>

16_(Understanding) Event processing-the way of passing data through mark

8. Pass data data-(passed attribute value name) to the logic, another way: mark: (passed attribute value name)

mark will merge the data passed by all sub-components or all marks in the current component into one object - you can get the mark data in the event object. Compared with data-(), you don't need to consider currentTarget or target, but data-() It is a set of codes for html and mini programs, and mark is a unique code for mini programs, so in summary

If you can clearly understand the difference between data-() currentTarget and target, use data()-

I don't know if I can use mark as an alternative, but in the end I still have to understand the difference between currentTarget and target - -

Difference: 1.target is the element that triggers the event. This is 2.currentTarget is the element that handles the event (more commonly used)

image-20230119110753043

<!-- 8.给逻辑传递数据, 另外一种方式: mark -->
<view 
  class="mark"
  bindtap="onMarkTap"
  data-name="why"
  data-age="18"
  mark:name="kobe"
  mark:age="30"
>
 <text mark:address="洛杉矶" class="title">mark</text>
</view>


// mark的数据传递
 onMarkTap(event) {
    
    
  console.log(event);
  const data1 = event.target.dataset
  // 点击外层的传递数据的结果
  console.log(data1);//{}
  const data2 = event.mark
  console.log(data2);//{address: "洛杉矶", age: "30", name: "kobe"}
  const data3 = event.currentTarget.dataset
  console.log(data3);// {age: "18", name: "why"}
  }

Chapter 3: Component Development of Mini Programs

image-20230119110902590

17_(Understand) Componentization-the componentization idea and application structure of small programs

image-20230119111702461

18_(Master) Componentization-Customized components and usage process

image-20230119113522413

image-20230119113531857

Where to create the component

If it is a public component, we put it under the components folder of the top-level folder. If it is just a component for this page, we directly create it and create the corresponding folder under this file.

The difference between components and ordinary pages

That is, "component": true exists in the .json file in the component, and is instantiated through Component instead of Page in the .js file.

Use of components

1. Built-in components can be used directly

2. Custom components must be configured when using them. They need to be configured in the json folder where they are used – key-value pairs.

index.json
"section-info": "/components/section-info/section-info",
     
 <!-- 2.自定义组件 -->
<section-info/>    

image-20230119114000586

19_(Understanding) Componentization-Supplementary style details of custom components

[The external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-eTaam6gj-1675304560123) (null)]

[The external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-vaU1fMLA-1675304560175) (null)]

07_learn_cpns

{
    
    
 "usingComponents": {
    
    
   "test-style": "/components/test-style/test-style"
 }
}

<!-- 3.测试组件样式 -->
<test-style/>
<view class="title">我是页面的title</view>

.title {
    
    
 background-color: skyblue;
}

test-style

// components/test-style/test-style.js

Component({
    
    
  options: {
    
    
    // 在实际开发中最好还是用isolated,完全隔离
    styleIsolation: "shared"
  }
})

{
    
    
  "component": true,
  "usingComponents": {
    
    }
}

<!--components/test-style/test-style.wxml-->
<view>----------测试样式的组件-----------</view>
<view class="title">我是组件的标题</view>

/* components/test-style/test-style.wxss */
.title {
    
    
  font-size: 36rpx;
  color: red;
}
/* 可以生效,但是副作用太大,强烈不建议使用 */
/* view {
  background-color: orange;
} */

20_(Master) Componentization-Component Communication-Properties Transfer Data

image-20230119121028421

image-20230119121108937

image-20230119123317882

index.wxml

{
    
    
  "usingComponents": {
    
    
    "section-info": "/components/section-info/section-info",
    "test-style": "/components/test-style/test-style"
  }
}

<!-- 2.自定义组件 -->
<section-info 
  info="abc" 
  title="我与地坛" 
  content="要是有些事情我没说, 别以为是我忘记了"
  bind:titleclick="onSectionTitleClick"
/>
<section-info info="cba" title="黄金时代" content="在我一生中最好的黄金时代, 我想吃, 我想爱"/>
    
    

section-info

// components/section-info/section-info.js
Component({
    
    
  properties: {
    
    
    title: {
    
    
      type: String,
      value: "默认标题"
    },
    content: {
    
    
      type: String,
      value: "默认内容"
    }
  },
})

{
    
    
  "component": true,
  "usingComponents": {
    
    }
}

<!--components/section-info/section-info.wxml-->
<view class="section">
  <view class="title" bindtap="onTitleTap">{
    
    {
    
     title }}</view>
  <view class="content info">{
    
    {
    
     content }}</view>
</view>

/* components/section-info/section-info.wxss */
.section .title {
    
    
  font-size: 40rpx;
  font-weight: 700;
  color: red;
}

.section .content {
    
    
  font-size: 24rpx;
  color: purple;
}

21_(Understand) Componentization-Component Communication-ExternalClasse–Transmitting Styles to Components

image-20230119124449210

external definition

定义
<section-info info="cba" title="黄金时代" content="在我一生中最好的黄金时代, 我想吃, 我想爱"/>
设置样式
.cba {
    
    
  background-color: #00f;
}

internally accepted

接受
externalClasses: ["info"],
使用    
<view class="section">
  <view class="title" bindtap="onTitleTap">{
    
    {
    
     title }}</view>
  <view class="content info">{
    
    {
    
     content }}</view>
</view>

22_(Master) Componentization-Component Communication-Components Emit Custom Events

image-20230119125803938

Subcomponents pass events

<!--1. 自定义事件 -->
  <view class="title" bindtap="onTitleTap">{
    
    {
    
     title }}</view>

methods: {
    
    
    // 2.将自定义事件传递出去,携带参数
    onTitleTap() {
    
    
      console.log("title被点击了~");
      this.triggerEvent("titleclick", "aaa")
    }
  }

The parent component accepts the event and handles the event bind:titleclick (event name) = "onSectionTitleClick" (defines the parent component's event name)

<!--3.父组件接受事件,处理事件  bind:titleclick(事件名)="onSectionTitleClick"(定义父组件处理事件名) -->
<section-info 
  info="abc" 
  title="我与地坛" 
  content="要是有些事情我没说, 别以为是我忘记了"
  bind:titleclick="onSectionTitleClick"
/>
// 4.父组件处理事件,携带的参数放在event.detail中
  onSectionTitleClick(event) {
    
    
    console.log("区域title发生了点击", event.detail);
  },

23_(Master) Componentization-Case exercise of component communication (write by yourself)

image-20230119130648711

Case implementation steps

parent component

1.引用子组件,将数据传递个子组件
<!-- 4.tab-control的使用 -->
<tab-control
  class="tab-control"
  titles="{
    
    {digitalTitles}}"
  bind:indexchange="onTabIndexChange"
/>
2.接受子组件传递的对应方法,接受参数,实现对应处理
 onTabIndexChange(event){
    
    
    const index = event.detail
    console.log("点击了", this.data.digitalTitles[index]);
  }

Subassembly

1.通过properties接收父组件传递过来的数据,展示数据

<!--components/tab-control/tab-control.wxml-->
<view class="tab-control">
  <block wx:for="{
    
    { titles }}" wx:key="*this">
    <view 
      class="item {
    
    {index === currentIndex ? 'active': ''}}"
      bindtap="onItemTap"
      data-index="{
    
    {index}}"
    >
      <text class="title">{
    
    {
    
     item }}</text>
    </view>
  </block>
</view>

2.向父组件传递函数,参数
// components/tab-control/tab-control.js
Component({
    
    
  properties:{
    
    
    titles:{
    
    
      type:Array,
      value:[]
    }
  },
  data:{
    
    
    currentIndex:0
  },
  methods:{
    
    
    onItemTap(event){
    
    
      const currentIndex = event.currentTarget.dataset.index
      this.setData({
    
    currentIndex})
      // 自定义事件
      this.triggerEvent("indexchange",currentIndex)
    }
  }
})

Detailed steps in the case tab

1. Define the sub-component structure and define the required variables and properties – write the style

2. The js file receives the data and custom properties passed by the parent component, defines fixed data and binding methods – and delivers custom events to the parent component.

3. The parent component definition data is passed to the child component data

4. The parent component accepts the child component’s custom events and processes the logic

24_(Comprehension) Content Review and Assignment

Chapter 3: Homework Assignment

1. Complete all the codes in the class

2. What is the difference between wx:if and hidden attributes? How to choose during development?

3. Why does wx:for need to bind key? What are the ways to bind keys?

4. What is the role of WXS? how to use?

5. What are the methods for passing parameters through events? How to pass parameters?

6. What is the difference between target and currentTarget?

7. What are the key details of styles in components? (summarize by yourself)

8. How do pages and components transfer data? What delivery methods are included?

9. How to use the component slots in the mini program? How to pass default value to slot?

Guess you like

Origin blog.csdn.net/SOLar7SysteM/article/details/128845580