小程序的基本组成结构
微信小程序的目录结构通常包括以下主要部分:
-  
app.json: 整个小程序的全局配置文件,用于配置小程序的一些基本信息,如页面路径、窗口样式、tabBar、网络超时等。
 -  
pages 文件夹: 用于存放小程序的页面文件,每个页面通常包括
.wxml(模板文件)、.wxss(样式文件)、.js(逻辑文件)、.json(页面配置文件)四个文件。例如,pages/index文件夹包含小程序的首页。 -  
utils 文件夹: 可选的文件夹,用于存放一些工具类、通用函数或者封装的功能模块,以便在不同页面中复用。
 -  
components 文件夹: 可选的文件夹,用于存放自定义组件,以便在不同页面中引用和复用。每个组件也包括
.wxml、.wxss、.js和.json四个文件。 -  
images 文件夹: 用于存放小程序中使用的图片资源,如图标、背景图等。
 -  
app.js: 小程序的全局逻辑文件,通常包含小程序的生命周期函数、全局变量和全局函数。
 -  
app.wxss: 小程序的全局样式文件,用于设置全局的样式、主题色等。
 -  
project.config.json: 小程序项目的配置文件,包含一些项目配置信息,如开发者工具配置、插件配置等。
 -  
sitemap.json: 用于配置小程序的页面索引,以便搜索引擎收录。
 -  
其他文件: 除了上述主要部分,还可以根据需要添加其他文件,如音频文件、视频文件、第三方库等。
 
小程序的目录结构可以根据项目的需求进行调整和扩展,但通常遵循上述的基本结构。在开发小程序时,合理的目录结构可以使代码更有组织性,便于团队协作和维护。
wxml和html的区别
html:div,  span, img,   a
对应
wxml:view, text, image, navigator
 
html:<a href=“#”>超链接</a>
wxml:<navigator url=" /pages/home/home"></navigator>
 
wxss和css区别
- 新增rpx尺寸单位
 - 提供了全局样式和局部样式
 - wxss仅支持部分css选择器
.class和#idelement
并集选择器、后代选择器
::after和::before等伪类选择器 
js文件的分类
小程序中的JS文件分为三大类,分别是:
- app.js
是整个小程序项目的入口文件,通过调用App()函数来启动整个小程序 - 页面的.js 文件
是页面的入口文件,通过调用Page()函数来创建并运行页面 - 普通的.js文件
是普通的功能模块文件,用来封装公共的函数或属性供页面使用 
宿主环境
宿主环境( host environment)指的是程序运行所必须的依赖环境。例如:
 Android 系统和iOS 系统是两个个同的伯土个境。女平队bAI7 Pp在心的LAndroid是安卓软件的宿主环境,脱离了宿主环境的软件是没有任何意义的!
小程序的宿主环境
就是微信
小程序的启动过程
- 把小程序的代码包下载到本地
 - 解析app.json 全局配置文件
 - 执行app.js小程序入口文件,调用App()创建小程序实例
 - 渲染小程序首页
 - 小程序启动完成
 
页面的渲染过程
- 加载解析页面的.json配置文件
 - 加载页面的.wxml模板和.wxss样式
 - 执行页面的.js文件,调用Page()创建页面实例
 - 页面渲染完成
 
常用的视图容器类组件
- view
普通视图区域
类似于HTML中的div,是一个块级元素常用来实现页面的布局效果 - scroll-view
可滚动的视图区域
常用来实现滚动列表效果 - swiper 和swiper-item
轮播图容器组件和轮播图item组件 
小程序官方把API分为了3类
- 事件监听API
 - 同步API
 - 异步API
 
数据绑定
使用mustach语法,跟vue很像:{{ }}
target和currentTarget区别

 总结就是target是源头组件,
 而currentTarget是触发事件的组件
事件传参
- 添加一个data-*属性
 
<button data-num="2" bindtap="handleButtonClick">点击按钮</button>
 
- 方法中通过事件对象 e 来获取传递的值
 
Page({
  handleButtonClick: function(e) {
    const num = e.currentTarget.dataset.num; // 通过事件对象获取data-num的值
    console.log('传递的值是:', num); // 输出传递的值
  }
});
 
inputHandler可以用来处理实时接受input中的值
<input id="Add2Input" type="number" placeholder="输入数字" bindinput="inputhandler"/>
 
Page({
  inputhandler: function(e) {
    console.log("hello");
    console.log(e.detail.value); // 打印用户输入的内容
  },
});
 
页面配置和全局配置的关系
小程序中,app.json中的window节点,可以全局配置小程序中的每一个页面的窗口表现。
实现页面导航的两种方式
- 声明式导航
使用<navigator>导航组件,通过点击<navigator>组件实现页面跳转 - 编程式导航
调用小程序导航API,实现页面跳转 
⭐️声明式导航跳转到tabBar界面
<!-- 在WXML中使用switchTab实现声明式导航到TabBar页面 -->
<navigator url="/pages/index/index" open-type="switchTab">
  <view class="link">点击跳转到首页(TabBar页面)</view>
</navigator>
 
⭐️声明式导航跳转到非tabBar界面
<!-- 在WXML中定义一个跳转链接 -->
<navigator url="/pages/about/about">
  <view class="link">点击跳转到关于页面</view>
</navigator>
 
声明式导航还可以实现后退导航
编程式导航导航跳转到tabBar界面
// 假设你要导航到底部 TabBar 中的某个页面,例如 "pages/index/index"
wx.switchTab({
  url: '/pages/index/index' // 替换成你要跳转的页面路径
})
 
编程式导航跳转到非tabBar界面
// 在某个事件处理函数或方法中执行导航操作
wx.navigateTo({
  url: '/pages/other-page/other-page' // 替换成你要跳转的页面路径
})
 
开发中更推荐使用编程式导航实现后退效果
<view>
  <button bindtap="goBack">返回</button>
</view>
 
// 在页面的 JavaScript 中
goBack: function () {
  wx.navigateBack({
    delta: 1, // 返回上一个页面
  });
}
 
导航传参
- 声明式导航传参
 
<navigator url=“/pages/info/info?name=zs&age=20”>跳转到info页面</navigator>
 
- 编程式导航传参
 
wx.navigateTo({
  url: '/pages/info/info?name=zs&age=20'
});
 
在onLoad中接收导航参数
Page({
  onLoad: function (options) {
    // options 包含了通过 URL 传递的参数
    const param1 = options.param1;
    const param2 = options.param2;
    
    // 在这里可以使用参数进行逻辑操作
  },
  // ...
});
 
下拉刷新
- 全局开启下拉刷新
在app.json的window节点中,将enablePullDownRefresh设置为true - 局部下拉刷新
在页面的.json配置文件中,将enablePullDownRefresh设置为true - 配置下拉刷新窗口的样式
在页面的.json配置文件中,通过backgroundColor和backgroundTextStyle来配置下拉刷新窗口的样式 - 监听页面的下拉刷新事件
onPullDownRefresh()函数 - 停止下拉刷新的效果
 
调用Wx.stopPullDownRefresh()可以实现停止刷新
上拉触底
- 监听上拉触底
在页面的.js文件中,通过onReachBottom()函数实现 
展示loading效果
使用wx.showLoading({})展示loading效果
 使用wx.hideLoading({})隐藏loading效果
对上拉触底进行节流处理
自定义编译模式
小程序的生命周期
- 生命周期的分类
应用生命周期
页面生命周期 - 生命周期函数的分类
应用生命周期函数
onLaunch()只会全局触发一次
onShow()小程序从后台进入前台时调用
onHide()
页面生命周期函数
onLoad只调用一次
onShow
onReady只调用一次
onHide
onUnload只调用一次 
wxs
wxs和javascript的区别
-  
wxs有自己的数据类型
 -  
wxs不支持类似于ES6及以上的语法
不支持: let、const、解构赋值、展开运算符、箭头函数、对象属性简写、et…
支持: var定义变量、普通function函数等类似于ES5的语法 -  
wxs遵循CommonJS语法规范
 
内嵌wxs脚本
wxs代码可以编写在wxml文件中的<wxs>标签内,就像Javascript 代码可以编写在html文件中的<script>标签内一样。
<!-- pages/index/index.wxml -->
<view>
  <text>{{ 2 + 3 }}</text> <!-- 内嵌JavaScript表达式 -->
  
  <wxs module="math">
    // 定义一个WXS函数
    var add = function (a, b) {
      return a + b;
    }
    
    // 导出函数
    module.exports = {
      add: add
    }
  </wxs>
  <text>{{ math.add(2, 3) }}</text> <!-- 调用内嵌WXS函数 -->
</view>
 
外联wxs脚本
<!-- pages/index/index.wxml -->
<view>
  <text>{{ utils.add(2, 3) }}</text>
</view>
 
定义外联wxs脚本
// utils.wxs
// 定义一个加法函数
var add = function (a, b) {
  return a + b;
}
// 导出函数,以便在WXML中使用
module.exports = {
  add: add//微信中不支持简写形式
}
 
引入外联wxs脚本
<!-- pages/index/index.wxml -->
<view>
  <wxs src="/path/to/external.wxs" module="externalModule"></wxs>
  <text>{{ externalModule.add(2, 3) }}</text> <!-- 调用外部WXS函数 -->
</view>
 
wxs的优点
<view>{{m2.toLower(country)}}</view>
 
自定义小组件
- 创建组件:在components文件夹下新建文件夹test,表示test组件存放位置,在test文件夹下右键选择新建componets就会自动生成所需要的文件
 - 组件引用:分为“全局引用”和“局部引用”
 
局部引用:
// pages/myPage/myPage.json
{
  "usingComponents": {
    "my-component": "/components/myComponent/myComponent"
  }
}
 
全局引入:
// app.json
{
  "usingComponents": {
    "my-component": "/components/myComponent/myComponent"
  }
}
 
组件和页面的区别
- 组件的.json文件中需要声明
“component”:true属性 - 组件的.js文件中调用的是
Component()函数,页面调用的是Page()函数 - 组件的事件处理函数需要定义到
methods节点中,页面直接写在Page()函数中 
组件的样式隔离
修改组件的样式隔离选项
在.js文件中新增如下配置:
Component({
  options: {
    styleIsolation: 'apply-shared' // 可以选择 "isolated", "apply-shared", 或 "shared"
  },
  // 组件的其他定义
})
 
 
自定义组件的数据、方法和属性
data数据
用于渲染组件模板的私有数据methids方法
事件处理函数和自定义方法properties属性
用来接受外界传过来的数据
数据监听
observers
Component({
  properties: {
    inputValue: {
      type: String,
      value: ''
    }
  },
  observers: {
    'inputValue': function (newVal, oldVal) {
      // 当 inputValue 发生变化时,会触发这个函数
      console.log('输入框的值变化了:', newVal);
      
      // 在这里可以执行其他逻辑,例如根据输入内容做搜索等操作
    }
  },
  // 组件的其他定义
})
 
纯数据字段
定义纯数据字段
Component({
  options: {
    // 指定_开头的数据字段为纯数据字段
    pureDataPattern: /^_/
  }
  data: {
  	a:true,//非纯数据字段
  	_a:true,//纯数据字段
  }
})
 
自定义组件的生命周期
created: 组件实例被创建时触发,此时组件数据 data 尚未初始化。
attached: 组件实例被附加到页面节点树时触发,可以在这里访问组件的属性和数据。
ready: 组件布局完成,可以在这里执行一些初始化工作,如请求数据、更新界面等。
moved: 组件被移动到另一个节点时触发,一般很少使用。
detached: 组件实例被销毁时触发,可以在这里释放资源、取消订阅等清理工作。
Component({
  data: {
    message: 'Hello from component!'
  },
  lifetimes: {
    created() {
      console.log('组件被创建');
    },
    attached() {
      console.log('组件被附加到页面');
    },
    ready() {
      console.log('组件已经准备就绪');
    },
    moved() {
      console.log('组件被移动');
    },
    detached() {
      console.log('组件被销毁');
    }
  }
})
 
组件所在页面的生命周期
show
 hide
 resize
插槽
<!-- custom-component.wxml -->
<view class="custom-component">
  <slot name="header"></slot>
  <view class="content">
    <!-- 默认内容 -->
    <slot></slot>
  </view>
</view>
 
定义了两个插槽:一个是具名插槽 “header”,另一个是默认插槽,没有指定名称。
<!-- 使用自定义组件的页面 -->
<custom-component>
  <!-- 将内容传递给名为 "header" 的插槽 -->
  <view slot="header">这是自定义头部</view>
  <!-- 默认内容会填充到默认插槽中 -->
  <view>这是默认内容</view>
</custom-component>
 
子组件项父组件传递信息
在子组件.js文件中
Component({
  methods: {
    sendDataToParent() {
      const data = { message: 'Hello from child' };
      this.triggerEvent('customEventName', data);
    }
  }
})
 
父组件的wxml
<child-component bind:customEventName="handleCustomEvent"></child-component>
 
父组件的.js文件中
Page({
  handleCustomEvent(event) {
    console.log('Received data from child:', event.detail);
    // 在这里处理子组件传递的数据
  }
})
 
父组件中获取子组件的实例
<!-- 子组件的 .wxml 文件 -->
<view id="child-component">
  <!-- 子组件的内容 -->
</view>
 
// 父组件的 .js 文件
Page({
  onReady: function () {
    // 获取子组件的实例
    const childComponent = this.selectComponent('#child-component');
    console.log(childComponent);
  }
})
 
小程序组件中behaviors使用
创建behavior
创建一个独立的 Behavior 文件,它通常以 .js 后缀为扩展名。在这个文件中定义你想要复用的属性、数据和方法
// myBehavior.js
const myBehavior = Behavior({
  properties: {
    myProperty: String, // 用于接收父组件传递的数据
  },
  data: {
    count: 0, // 组件内部的数据
  },
  methods: {
    increment() {
      this.setData({ count: this.data.count + 1 });
    },
  },
});
module.exports = myBehavior;
 
导入并使用behavior
// myComponent.js
const myBehavior = require('../../behaviors/myBehavior');
Component({
  behaviors: [myBehavior], // 引用上面创建的 Behavior
  properties: {
    // 组件的属性
  },
  data: {
    // 组件的数据
  },
  methods: {
    // 组件的方法
  },
});
 










