//index.wxml
{{message}}
//index.js
Page({
/**
- 页面的初始数据
*/
data: {
message: “你好”,
id:“item”
},
})
同样,双花括号的写法也可以写在指令里面,比如:
//index.wxml
//指令wx:if这些个是渲染条件,具体看下一节,这里看个大概就好
{{message}}1
{{message}}2
{{message}}3
//index.js
Page({
/**
- 页面的初始数据
*/
data: {
code:1
},
})
这样,如果code的值为1,那么第一个view后面的值就是ture,那么此时页面上就会渲染第一个view,剩下的就不再执行,同理code为2的时候,只有第二个后面是true,那么只会渲染第二个view;
==============================================================
小程序中的列表渲染使用的指令是:wx:for,用法几乎和vue中的一样,先看个例子:假设现在从服务器请求到了一个数组,数组中每一项都是一个对象,其中有一个id值,需要绑定在列表上的每个id属性,并且将值打印出来
- {{item.id}}-{{index}}
//index.js
Page({
data: {
array:[
{
id:“item1”
},
{
id:“item2”
},
{
id:“item3”
}
]
}
})
通过双花括号,可以将data中的数组array获取到,之后通过wx:for的指令,将数组进行遍历,之后变量item代表对应的每一项,index对应每一项的下标值;
注意的是,为了保证列表改变时,每一项都可以被小程序内部追踪到,因此需要绑定一个key值,比如上例,将id值绑定给key
- {{item.id}}-{{index}}
key的绑定不需要双花括号,也不需要item.之类的操作,其中的的变量都是每一项对象内的的键值;另外,假设获得的数组,每一项就是一个数字或者字符串,此时没有对应的属性名,那么可以使用保留字_this,这个_this就是每一项本身,比如:
- {{item}}
//index.js
Page({
data: {
array:[1, 2, 3]
}
})
小程序中的条件渲染使用的指令是wx:if,wx:elif,wx:else,用法和vue基本一致,看个示例:
//指令wx:if
{{message}}1
{{message}}2
{{message}}3
//index.js
Page({
/**
- 页面的初始数据
*/
data: {
code:1
},
})
wx:if将判断=号后面的值是否为true,只有值为true的时候才会渲染对应的部分,注意的是wx:if是真的渲染不渲染,假如为false,那么该部分是不会被渲染进DOM树的,如果要使用的是类似于v-show这种渲染进dom树,但是不显示,则使用指令:hidden
{{message}}1
此时的view不管hidden后面的是true还是false,都会将该部分渲染进DOM中,只是true的时候是显示的,false的时候是隐藏的;
如果在项目中的某一部分是需要经常的切换显示隐藏,那么使用hidden比较好,如果不是太频繁,那么使用wx:if比较好;
模版,template,可以理解成一段可重复使用的代码片段,这些代码片段只需要定义一次,就可以不断的重复使用,比如:
//index.wxml
FirstName: {{firstName}}, LastName: {{lastName}}
通过template定义了一个模版,并且给这个模版命名了一个名字staffName,使用的使用只需要通过名字就可以指定需要使用哪个模版了
//index.wxml
//index.js
Page({
data: {
person:{
name:“oliver”,
age:18
}
}
})
这里模版被使用了3次,通过is属性,指定要使用模版的名字,通过data属性注入数据,当然,模版的名字也是支持双花括号语法的,比如
FirstName: {{firstName}}, LastName: {{lastName}}
通常,如果项目中有好些相同的布局,那么就可以考虑抽离出来,单独存放,然后项目中往往是组合使用,比如使用的时候通过条件渲染模版,当获取到的状态是1的时候渲染的是模版1,如果状态是2的时候渲染的是模版2等等;
这里又出现了一个新问题,如果模版在页面a中,那么在这么在页面b中也使用这个模版?答案是通过import或include引入;
引用
import
//在demo1.wxml中定义了一个template
//当然demo1.wxml中肯定还有很多其他代码,但是模版和其他代码不冲突
{{age}}-{{name}}
//在demo2.wxml引入,src后面跟随着的是需要引入的文件的路径
import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template,举个例子:C import B,B import A,在C中可以使用B定义的template,在B中可以使用A定义的template,但是C不能使用A定义的template;
**
include
和import不同,import会引入目标文件中的template,而include则是会引入 、外的所有代码,也就是说,会将整个页面都拷贝过来了;
比如现在所有的页面都需要使用相同的header和相同的footer,那么就可以将header和footer单独写一个文件,其他所有页面都使用include引入
body
header
footer
===============================================================
WXS是小程序的一套脚本语言,它的语法和JavaScript不完全一致,WXS代码可以编写在wxml的标签中,也可以写在以.wxs为后缀的文件内;
为什么要有WXS,作用上看它和JavaScript几乎一致,官网上写到:由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。这个速度差异其实很明显,尤其是项目比较大的时候;
每个.wxs文件和标签都是一个独立的模块;都有其自己独立的作用域,每一个模块内的变量与函数,默认都是私有的,这就代表如果要被其他模块使用,必须通过module.exports实现,看个例子
var msg = “hello world”;
module.exports.message = msg;
{{m1.message}}
这个是一个页面渲染的例子,基本上就是如果要使用wxs内的变量,必须通过module.exports导出,否则就无法识别,再看一个数据处理的例子:
// index.js
Page({
data: {
array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
}
})
//index.wxml
var getMax = function(array) {
var max = undefined;
for (var i = 0; i < array.length; ++i) {
max = max === undefined ?
array[i] :
(max >= array[i] ? max : array[i]);
}
return max;
}
module.exports.getMax = getMax;
// 调用 wxs 里面的 getMax 函数,参数为 index.js 里面的 array
{{m1.getMax(array)}}
同样,如果是新建了一个wxs文件
var name = “我的名字是Oliver”;
var bar = function(d){
return d;
}
module.exports = {
name:name,
func:bar
}
那么在wxml文件中需要先指明路径,比如:
//wxml文件
//通过src属性引入wxs文件,然后通过module命名模块
{{m2.name}}
{{m2.func(“大家好”)}}
另外,如果现在有两个wxs文件,分别为a.wxs和b.wxs,如果要在b.wxs中引用a.wxs,那么可以通过require引入,比如:
//a.wxs
var foo = “‘hello world’ from tools.wxs”;
var bar = function (d) {
return d;
}
module.exports = {
FOO: foo,
bar: bar,
};
module.exports.msg = “some msg”;
//b.wxs
var tools = require(“./a.wxs”);
console.log(tools.FOO);
console.log(tools.bar(“logic.wxs”));
console.log(tools.msg);
注意的是,require后面的路径必须是相对路径,另外如果多个wxs文件的module重名了,那么写在后面的将覆盖前面的;
==============================================================
小程序的事件系统和JS的事件系统的用法基本是一致的,区别在于事件名不一样,因此具体的事件相关请看参考文档 WXML - 事件;
先看个简单的例子:
Click me!
//错误示例
<view bindtap=“tapName(“oliver”)”> Click me!
这种传递参数是错误的,微信小程序不支持这种方式传递参数
这里view标签上通过bindtap绑定了一个tapName事件,作用是当用户点击到当前这个view时就会触发tapName函数,而tapName函数则写在对应的js文件中
Page({
/**
- 页面的初始数据
*/
data: {
message: “你好”,
id:“adb”,
person:{
name:“oliver”,
age:18
}
},
tapName: function(event) {
console.log(event)
}
})
同样,小程序中的事件分为冒泡事件和非冒泡事件,冒泡事件简单的说,就是组件上的事件被触发以后,会向其父节点传递,举个例子
Click me!
点击了button上的bindtap触发click函数之后,其父元素伤的bindtap同样会被触发,这就是冒泡,小程序中的冒泡事件大致有以下:
看到这里可能有疑惑,为什么事件类型中没有bind这个词,上面例子中明明是用的bindtap,表里面为什么仅仅是tap?实际上bind是一个修饰词,可以理解成是类似于bue中的v-on,v-bind这种,在小程序中bind代表的是普通事件绑定,换个可以更好理解的写法,bind:,具体示例:
Click me!
通过bind修饰的事件,就是普通事件,普通事件不会对事件进行处理,但处理事件的函数名必须是字符串,因此,传参,如下例是不行的,因为小程序会将后面整体视作是一个字符串
Click here!
通过catch修饰事件,通过catch修饰的事件,会阻止其冒泡行为
Click here!
通过mut-bind修饰的事件,代表互斥事件,一个 mut-bind 触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind 绑定函数不会被触发,但 bind 绑定函数和 catch 绑定函数依旧会被触发;
outer view
middle view
inner view
上例中,函数handleTap3被触发后,事件冒泡到父节点,之后handleTap2会被触发,再之后事件继续冒泡到父节点,但是此时的outer上的绑定也是互斥事件,因此handleTap1将不会被触发;
捕获阶段在冒泡阶段之前,采用的修饰是capture-bind和capture-catch,
capture-bind:代表当组件处于捕获阶段时监听事件并触发相关函数,之后按正常的捕获和冒泡流程走;
capture-catch:和capture-bind不同,capture-catch在触发事件后,会取消之后的捕获和冒泡流程,相当于直接终止了之后的流程;
outer view
inner view
这段代码中,如果是capture-bind,那么所有的事件都会被触发,并且触发的流程是:handleTap2、handleTap4、handleTap3、handleTap1;
但如果将capture-bind替换成capture-catch,在触发第一个touchstart后,它就会终止之后的所有流程,因此,只会触发一个handleTap2函数;
==============================================================
理解起来和vue的生命周期有点类似,简单的说,就是在小程序在运行的过程中,会经历过不同的阶段,在不同的阶段会抛出一些函数,称为钩子函数,这些钩子函数中的代码会在这个阶段中被运行,因此在不同的阶段可以做一些特定的处理,比如获取服务器信息,比如初始化数据等等,而这些钩子函数统称为生命周期,因为运行这些钩子函数的阶段囊括了从小程序的创建到销毁;
小程序的生命周期分为两种,一种是小程序本体的,另外一种是各个页面的
小程序的生命周期是写在app.js中的
//app.js
App({
//监听小程序初始化
onLaunch: function () {},
//监听小程序启动或切前台,小程序在后台切到前台的时候会调用;
onShow: function(){},
//监听小程序切后台,小程序从前台切到后台的时候会调用;
onHide: function(){},
/*
-
发生错误是调用函数,在这个函数内,通常是用在监听线上小程序有没有发生错误的,
-
当发生错误时,触发这个函数,在这个函数内可以将错误提交到后台;
*/
onError: function(){},
/*
-
页面不存在时调用函数,比如,有时候印刷了一些小程序二维码做推广,但是因为一些特殊原因,
-
页面被删除了,那么此时就可以通过这个函数监听错误,提交后台,然后做一些兼容;
*/
onPageNotFound: function(){},
globalData: {
userInfo: null
}
})
这个globalData,这个属性是定义的一些全局属性,比如示例中的userInfo是存储的用户信息,比如在打开小程序后,获取当前用户的信息,赋值给userInfo,那么在之后的页面显示中都可以获取到当前的用户信息了;
//index.js等其他页面
var app = getApp()
Page({
/**
- 页面的初始数据
*/
data: {
message: “你好”,
id:“adb”,
person:{
name:“oliver”,
age:18
}
},
//打印
tapName: function(event) {
console.log(app.globalData.userInfo)
}
})
小程序的每个页面都有自己的生命周期,它的接收一个对象作为参数,其上有页面的初始化数据,生命周期回调,事件处理函数
Page({
/**
- 页面的初始数据
*/
data: {},
/**
- 生命周期函数–监听页面加载
*/
onLoad: function (options) {},
/**
- 生命周期函数–监听页面初次渲染完成,第一次打开页面完成之后触发
*/
onReady: function () {},
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
结尾
正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。
以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。
己的生命周期,它的接收一个对象作为参数,其上有页面的初始化数据,生命周期回调,事件处理函数
Page({
/**
- 页面的初始数据
*/
data: {},
/**
- 生命周期函数–监听页面加载
*/
onLoad: function (options) {},
/**
- 生命周期函数–监听页面初次渲染完成,第一次打开页面完成之后触发
*/
onReady: function () {},
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-ZKzFRpqQ-1712272418705)]
[外链图片转存中…(img-baXcW13v-1712272418705)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-1doDm9of-1712272418705)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
结尾
正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。
以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。