赞
踩
可在父组件里调用 this.selectComponent ,获取子组件的实例对象 --1.获取对应的组件实例对象–通过定义的class获取
页面直接调用组件方法—必须给组件定义一个class类便于获取组件
子组件方法 test(index) { console.log("tab control test function exec"); this.setData({ currentIndex: index }) } 父组件 必须给组件定义一个class类便于获取组件 <!-- 4.tab-control的使用 --> <tab-control class="tab-control" titles="{{digitalTitles}}" bind:indexchange="onTabIndexChange" /> <!-- 必须给组件定义一个class类便于获取组件 --> <button bindtap="onExecTCMethod">调用TC方法</button> 父组件在方法中调用子组件 onExecTCMethod() { // 1.获取对应的组件实例对象--通过定义的class获取 const tabControl = this.selectComponent(".tab-control") // 2.调用组件实例的方法 tabControl.test(2) }
要点:小程序中slot插槽不支持默认值
通过css实现插值默认值,通过兄弟选择器
<view class="content">
<!-- 小程序中插槽是不支持默认值的 -->
<slot></slot>
</view>
<view class="default">哈哈哈哈</view>
.default {
display: none;
}
.content:empty + .default {
display: block;
}
代码实现
my-slot
<!--components/my-slot/my-slot.wxml--> <view class="my-slot"> <view class="header">Header</view> <view class="content"> <!-- 小程序中插槽是不支持默认值的 --> <slot></slot> </view> <view class="default">默认值</view> <view class="footer">Footer</view> </view> /* components/my-slot/my-slot.wxss */ .my-slot { margin: 20px 0; } .default { display: none; } .content:empty + .default { display: block; }
08_learn_slot
{ "usingComponents": { "my-slot": "/components/my-slot/my-slot" } } <!--pages/08_learn_slot/index.wxml--> <!-- 1.单个插槽的使用 --> <my-slot> <button>我是按钮</button> </my-slot> <my-slot> <image src="/assets/nhlt.jpg" mode="widthFix"></image> </my-slot> <my-slot></my-slot>
-多个插槽的使用需要给插槽命名(具名插槽)和在Component实例中设置options:{multipleSlots:true}
1.使用多个插槽需要在Component实例中设置options:{multipleSlots:true}
2.给插槽命名具名插槽
3.给组件设置样式
4.在页面中json中注册组件usingComponents
5.使用组件–给标签添加slot属性并指定查找名
1.// components/mul-slot/mul-slot.js Component({ options: { multipleSlots: true } }) 2. <!--components/mul-slot/mul-slot.wxml--> <view class="mul-slot"> <view class="left"> <!-- 具名插槽 --> <slot name="left"></slot> </view> <view class="center"> <slot name="center"></slot> </view> <view class="right"> <slot name="right"></slot> </view> </view> 3. /* components/mul-slot/mul-slot.wxss */ .mul-slot { display: flex; text-align: center; } .left, .right { width: 160rpx; } .center { flex: 1; } 4. { "usingComponents": { "mul-slot": "/components/mul-slot/mul-slot" } } 5. <!-- 2.多个插槽的使用 --> <mul-slot> <!-- 给标签添加slot属性并指定查找名 --> <button slot="left" size="mini">left</button> <view slot="center">哈哈哈</view> <button slot="right" size="mini">right</button> </mul-slot>
◼ behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins”。
混入的实现步骤
1.注册组件、使用组件
2.定义混入的js文件
3.在组件中·使用混入,导入、注册、使用
1. "c-behavior": "/components/c-behavior/c-behavior" <!-- 3.组件的混入 --> <c-behavior/> 2. export const counterBehavior = Behavior({ data: { counter: 100 }, methods: { increment() { this.setData({ counter: this.data.counter + 1 }) }, decrement() { this.setData({ counter: this.data.counter - 1 }) } } }) 3. // components/c-behavior/c-behavior.js // 使用类似mixins的behaviors的混入的步骤 // 1.导入 import { counterBehavior } from "../../behaviors/counter" // 2.注册 Component({ behaviors: [counterBehavior] }) <!--components/c-behavior/c-behavior.wxml--> <view> <!-- 3.使用混入的数据 --> <view class="counter">当前计数: {{counter}}</view> <button bindtap="increment">+1</button> <button bindtap="decrement">-1</button> </view>
1. <text>c-lifetime组件</text> // components/c-lifetime/c-lifetime.js Component({ // 组件生命周期的书写位置 lifetimes: { created() { console.log("组件被创建created"); }, attached() { console.log("组件被添加到组件树中attached"); }, detached() { console.log("组件从组件树中被移除detached"); } }, // 页面的生命周期 pageLifetimes: { show() { console.log("page show"); }, hide() { console.log("page hide"); } } }) 2. "c-lifetime": "/components/c-lifetime/c-lifetime" <!-- 4.组件的生命周期 --> <button bindtap="onChangeTap">切换</button> <c-lifetime wx:if="{{isShowLiftTime}}"/> // pages/08_learn_slot/index.js Page({ data: { isShowLiftTime: true }, onChangeTap() { this.setData({ isShowLiftTime: !this.data.isShowLiftTime }) } })
1.在onload中发起网络请求wx,request({})传入参数
2.在wxml中展示数据
1. // pages/09_learn_api/index.js Page({ data: { allCities: {}, houselist: [], }, onLoad() { // 1.网络请求基本使用 // wx.request({ // url: "http://123.207.32.32:1888/api/city/all", // success: (res) => { // const data = res.data.data // console.log(data); // this.setData({ allCities: data }) // }, // fail: (err) => { // console.log("err:", err); // } // }) wx.request({ url: "http://123.207.32.32:1888/api/home/houselist", data:{page:1}, success: (res) => { const data = res.data.data console.log(data); this.setData({ houselist: data }) } }) } }) 2. <!--pages/09_learn_api/index.wxml--> <view class="house-list"> <block wx:for="{{houselist}}" wx:key="{{item.data.houseId}}"> <view class="item"> <image src="{{item.data.image.url}}"></image> <view class="title">{{item.data.houseName}}</view> </view> </block> </view>
网络请求封装成函数实现步骤
1.在service文件夹中创建index.js文件,通过解构和promise封装
1-2.引入service文件夹中的index.js文件
2.使用封装的函数 promise有点并行的感觉,第一个请求的结果没出来之前也会发送第二个请求
3.await/async 同步 第一个请求的结果没出来之前不会发送第二个请求,容易堵塞,不过可以放到单独的方法中
4.将请求封装到一个单独函数中(推荐),异步方法不会阻塞。方法单独定义,在onLoad调用就行
5.下拉加载更多
1. // 封装成函数 export function hyRequest(options) { return new Promise((resolve, reject) => { wx.request({ ...options, success: (res) => { resolve(res.data) }, fail: reject }) }) } 1-2 // pages/09_learn_api/index.js import { hyRequest, hyReqInstance } from "../../service/index" Page({ data: { allCities: {}, houselist: [], currentPage: 1 }, async onLoad() { // 1.网络请求基本使用 // wx.request({ // url: "http://codercba.com:1888/api/city/all", // success: (res) => { // const data = res.data.data // this.setData({ allCities: data }) // }, // fail: (err) => { // console.log("err:", err); // } // }) // wx.request({ // url: 'http://codercba.com:1888/api/home/houselist', // data: { // page: 1 // }, // success: (res) => { // const data = res.data.data // this.setData({ houselist: data }) // } // }) 2. // 2.使用封装的函数 promise有点并行的感觉,第一个请求的结果没出来之前也会发送第二个请求, // hyRequest({ // url: "http://codercba.com:1888/api/city/all" // }).then(res => { // this.setData({ allCities: res.data }) // }) // hyRequest({ // url: "http://codercba.com:1888/api/home/houselist", // data: { // page: 1 // } // }).then(res => { // this.setData({ houselist: res.data }) // }) 3. // 3.await/async 同步 第一个请求的结果没出来之前不会发送第二个请求,容易堵塞,不过可以放到单独的方法中 // const cityRes = await hyRequest({ // url: "http://codercba.com:1888/api/city/all" // }) // this.setData({ allCities: cityRes.data }) // const houseRes = await hyRequest({ // url: "http://codercba.com:1888/api/home/houselist", // data: { page: 1 } // }) // this.setData({ houselist: houseRes.data }) 4. // 4.将请求封装到一个单独函数中(推荐),异步方法不会阻塞 this.getCityData() this.getHouselistData() // 5.使用类的实例发送请求 hyReqInstance.get({ url: "/city/all" }).then(res => { console.log(res); }) }, 5. async getCityData() { const cityRes = await hyRequest({ url: "http://codercba.com:1888/api/city/all" }) this.setData({ allCities: cityRes.data }) }, async getHouselistData() { const houseRes = await hyRequest({ url: "http://codercba.com:1888/api/home/houselist", data: { page: this.data.currentPage } }) const finalHouseList = [...this.data.houselist, ...houseRes.data] this.setData({ houselist: finalHouseList }) // 思考: 为什么这里不需要setData?因为页面不需要刷新 this.data.currentPage++ }, 5. // 下拉加载更多 onReachBottom() { this.getHouselistData() } })
可不可以怎么写
一个测试
hyRequest({
url: "http://codercba.com:1888/api/city/all"
}).then(res => {
this.setData({ allCities: res.data })
},err=>{console.log("err");})
1.先封装class的网络请求–封装成类
2.引入class
3.使用类的实例发送request请求
1. // 封装成类 -> 实例 class HYRequest { constructor(baseURL) { this.baseURL = baseURL } request(options) { const { url } = options return new Promise((resolve, reject) => { wx.request({ ...options, url: this.baseURL + url, success: (res) => { resolve(res.data) }, fail: (err) => { console.log("err:", err); } }) }) } get(options) { return this.request({ ...options, method: "get" }) } post(options) { return this.request({ ...options, method: "post" }) } } export const hyReqInstance = new HYRequest("http://codercba.com:1888/api") 2. import { hyRequest, hyReqInstance } from "../../service/index" 3. // 5.使用类的实例发送请求 hyReqInstance.get({ url: "/city/all" }).then(res => { console.log(res); }) // 6.使用类的实例发送request请求 // hyReqInstance.request({ // url: "/home/houselist?page=1" // }).then(res => { // this.setData({ houselist: res.data }) // })
<!--pages/10_learn_api/index.wxml--> <!-- 1.展示弹窗 --> <view> <button size="mini" bindtap="onShowToast">showToast</button> <button size="mini" bindtap="onShowModal">showModal</button> <button size="mini" bindtap="onShowAction">showAction</button> </view> // pages/10_learn_api/index.js Page({ // 1.弹窗相关的API onShowToast() { wx.showToast({ title: '购买失败!', icon: "error", duration: 1000, //蒙版:在未消失的时候可不可以点击后面的操作 mask: true, success: (res) => { console.log("res:", res); }, fail: (err) => { console.log("err:", err); } }) // wx.showLoading({ // title: "加载中ing" // }) }, onShowModal() { wx.showModal({ title: "确定购买吗?", content: "确定购买的话, 请确定您的微信有钱!", confirmColor: "#f00", cancelColor: "#0f0", success: (res) => { if (res.cancel) { console.log("用户点击取消"); } else if (res.confirm) { console.log("用户点击了确定"); } } }) }, onShowAction() { wx.showActionSheet({ itemList: ["衣服", "裤子", "鞋子"], success: (res) => { console.log(res.tapIndex); }, fail: (err) => { console.log("err:", err); } }) }, }
// 2.分享功能
onShareAppMessage() {
return {
title: "旅途的内容",
path: "/pages/favor/favor",
imageUrl: "/assets/nhlt.jpg"
}
},
对于用户的关键信息,需要获取用户的授权后才能获得:
app.json中配置 "permission": { "scope.userLocation": { "desc": "需要获取您的位置信息" } }, <!-- 3.设备信息 --> <button bindtap="onGetSystemInfo">设备信息</button> // 3.获取用户的设备信息 onGetSystemInfo() { // 1.获取手机的基本信息 // wx.getSystemInfo({ // success: (res) => { // console.log(res); // } // }) // 2.获取当前的位置信息 wx.getLocation({ success: (res) => { console.log("res:", res); } }) },
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y12gk531-1675304800111)(null)]
<!-- 4.本地存储 --> <button bindtap="onLocalStorage">本地存储</button> // 4.本地存储方式 onLocalStorage() { // 同步操作,执行完上一行,才可以执行下一行 // 1.存储一些键值对 // wx.setStorageSync('name', "why") // wx.setStorageSync('age', 18) // wx.setStorageSync('friends', ["abc", "cba", "nba"]) // 2.获取storage中内容 // const name = wx.getStorageSync('name') // const age = wx.getStorageSync('age') // const friends = wx.getStorageSync('friends') // console.log(name, age, friends); // 3.删除storage中内容 // wx.removeStorageSync('name') // 4.清空storage中内容 // wx.clearStorageSync() // 异步操作 ,执行的时候不会阻塞下一行代码的执行 wx.setStorage({ key: "books", data: "哈哈哈", // 加密但是有版本限制--2.21.3 encrypt: true, success: (res) => { wx.getStorage({ // 获取 key: "books", encrypt: true, success: (res) => { console.log(res); } }) } }) console.log("-------"); }
页面跳转存在页面栈–会记录页面跳转的记录,以下方法记录跳转的不同方法
页面跳转wx.navigateTo({})
<button bindtap="onNavTap">跳转</button> // pages/11_learn_nav/index.js Page({ data: { name: "kobe", age: 30, }, onNavTap() { const name = this.data.name const age = this.data.age // 页面导航操作 wx.navigateTo({ // 跳转的过程, 传递一些参数过去 url: `/pages2/detail/detail?name=${name}&age=${age}`, }) } }) 跳转过后的页面 // pages2/detail/detail.js Page({ data: { name: "", age: 0 }, onLoad(options) { // options里面就是跳转时携带的参数 console.log(options); const name = options.name const age = options.age this.setData({ name, age }) }, })
<button size="mini" type="primary" bindtap="onBackTap">返回</button>
onBackTap() {
// 1.返回导航
wx.navigateBack({
// 默认值是1.跳转上级页面目录
delta:2
})
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-voZBEjeV-1675304800287)(null)]
<view>{{message}}</view> message: "哈哈哈" detail <button size="mini" type="primary" bindtap="onBackTap">返回</button> onBackTap() { // 1.返回导航 wx.navigateBack() // 2.方式一: 给上一级的页面传递数据 // 2.1. 获取到上一个页面的实例 // const pages = getCurrentPages() // // console.log(pages);通过打印看当前页面和上一个页面的位置,通过pages[pages.length-2]获取到上一个页面 // const prePage = pages[pages.length-2] // // 2.2.通过setData给上一个页面设置数据 // prePage.setData({ message: "呵呵呵" }) }, // 页面卸载的生命周期,只用在这里写,就都可以实现了 onUnload() { // 2.1. 获取到上一个页面的实例 const pages = getCurrentPages() const prePage = pages[pages.length-2] // 2.2.通过setData给上一个页面设置数据 prePage.setData({ message: "呵呵呵" }) }
// pages/11_learn_nav/index.js Page({ data: { name: "kobe", age: 30, message: "哈哈哈" }, onNavTap() { const name = this.data.name const age = this.data.age 3. const that = this // 页面导航操作 wx.navigateTo({ // 跳转的过程, 传递一些参数过去 url: `/pages2/detail/detail?name=${name}&age=${age}`, // 方式二,通过 events:回调函数接受数据 2. events: { backEvent(data) { console.log("back:", data); const names = data.name 3. // 修改值携带进来 that.setData({name:names}) }, coderwhy(data) { console.log("why:", data); } } }) } }) onBackTap() { // 1.返回导航 wx.navigateBack() // 2.方式一: 给上一级的页面传递数据 // 2.1. 获取到上一个页面的实例 // const pages = getCurrentPages() // // console.log(pages);通过打印看当前页面和上一个页面的位置,通过pages[pages.length-2]获取到上一个页面 // const prePage = pages[pages.length-2] // // 2.2.通过setData给上一个页面设置数据 // prePage.setData({ message: "呵呵呵" }) 2. // 3.方式二: 回调events的函数 // 3.1. 拿到eventChannel const eventChannel = this.getOpenerEventChannel() // 3.2. 通过eventChannel回调函数 eventChannel.emit("backEvent", { name: "back", age: 111 }) eventChannel.emit("coderwhy", { name: "why", age: 10 }) },
<navigator open-type="navigateBack">返回</navigator>
<navigator class="nav" url="/pages2/detail/detail?name=why&age=18">跳转</navigator>
小程序登录不用登录账号和密码,因为直接在微信上登录
小程序通过openid来验证身份
如果账号注册公众号可以获取unionid
实现步骤登录逻辑
1.方式一:通过原生方法
import { hyLoginReqInstance } from "../../service/index" // pages/12_learn_login/index.js Page({ // onLoad登录的流程 async onLoad() { // 1.获取token, 判断token是否有值 const token = wx.getStorageSync('token') || "" // 2.发起请求--判断token是否过期 const res = await hyLoginReqInstance.post({ url: "/auth", header: { token: token } }) // console.log(res); // 2.如果token有值和无值的情况 if (token && res.message === "已登录") { console.log("请求其他的数据"); } else { this.handleLogin() } }, // 第一种写法 // handleLogin() { // // 1.获取code // wx.login({ // success: (res) => { // const code = res.code // // 2.将这个code发送自己的服务器(后端) // wx.request({ // url: "http://123.207.32.32:3000/login", // data: { // code // }, // method: "post", // success: (res) => { // const token = res.data.token // wx.setStorageSync('token', token) // } // }) // } // }) // } })
2.方式二:通过promise–
1.封装login的promise方法
2.封装成类的请求方法
3.onLoad登录的流程
3.1.获取token, 判断token是否有值
3.2.判断token是否过期
3.3如果token有值和无值的情况
4.第二种写法 --获取login接口处理函数获取token
login.js export function getCode(){ return new Promise((resolve,reject)=>{ wx.login({ success:(res)=>{ resolve(res.code) } }) }) } export const hyLoginReqInstance = new HYRequest("http://123.207.32.32:3000") import { getCode } from "../../service/login"; import { hyLoginReqInstance } from "../../service/index" // pages/12_learn_login/index.js Page({ // onLoad登录的流程 async onLoad() { // 1.获取token, 判断token是否有值 const token = wx.getStorageSync('token') || "" // 2.发起请求--判断token是否过期--判断token是否正确 const res = await hyLoginReqInstance.post({ url: "/auth", header: { token: token } }) // console.log(res); // 2.如果token有值和无值的情况 if (token && res.message === "已登录") { console.log("请求其他的数据"); } else { this.handleLogin() } }, // 第二种写法 --获取login接口处理函数获取token async handleLogin() { // 1.获取code const code = await getCode() // 2.使用code换取token const res = await hyLoginReqInstance.post({ url: "/login", data: { code } }) // 3.保存token wx.setStorageSync('token', res.token) } })
数据传递:
组件跳转
登录的身份的标题
登录流程
登录代码演练
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。