七、自定义组件2
1. mixin
//导出一个混入对象exportdefaultBehavior({//组件公共的数据data:{name:"我是一个自定义组件..."},//组件公共的方法methods:{sayHi(){console.log('hi...');}}})
2. tabBox组件
<viewclass="tab_box"><!-- 组件中的slot标签,用于定义插槽。使用组件时,两个组件标签中间的内容都会放到插槽中 --><slot></slot><viewclass="flex"><viewclass="tab {{active===index?'active':''}}"wx:key="index"wx:for="{{data}}"bindtap="click"data-i="{{index}}">{{item.title}}</view></view><viewclass="list"><viewclass="item {{active===index?'show':''}}"wx:key="index"wx:for="{{data}}">{{item.content}}</view></view></view>
@import'../../app.wxss';.tab_box{margin:10rpx;padding:10rpx;border:1pxsolid#eeeeee}.tab{padding:10rpx20rpx;border:1pxsolid#eeeeee;margin:02px;}.tab.active{background:orangered;color:#ffffff;}.list{border:1pxsolid#eeeeee;margin-top:10rpx;padding:10rpx;}.item{display:none;}.item.show{display:block;}
//导入混入对象importmixinfrom'../mixin'Component({//behaviors,用于给当前组件混入公共的内容behaviors:[mixin],//组件的生命周期lifetimes:{attached:function(){// 在组件实例进入页面节点树时执行console.log('加载该组件...');console.log(this.data.version);console.log(this.data.name);this.sayHi()},detached:function(){// 在组件实例被从页面节点树移除时执行console.log('移除该组件...');},},
//监听器:可以监听组件中的数据是否发生变化observers:{//这里根据数据的名称,定义同名的方法,用于监听该数据是否发生变化//该方法的参数,返回的是数据的最新值//当前数据的值发生变化时,需要做些什么的时候,通常会使用监听器。active(val){console.log(val);}},/**
* 组件的属性列表
*/properties:{data:{type:Array},active:{type:Number,value:0}},/**
* 组件的初始数据
*/data:{version:'1.0'},/**
* 组件的方法列表
*/methods:{click(e){let{i}=wx.$key(e)this.setData({active:i})//组件内部触发事件this.triggerEvent("change",i)},}})
3. table组件
<viewclass="table"><viewclass="header"><viewclass="item"wx:key="index"wx:for="{{column}}">{{item.title}}</view></view><viewclass="content"wx:key="index"wx:for="{{data}}"><viewclass="item"wx:key="index1"wx:for="{{column}}"wx:for-index="index1"wx:for-item="item1">{{item[item1.key]}}</view></view></view>
.table{margin:10rpx0;}.header,.content{display:flex;}.header.item,.content.item{padding:2px0;flex:1;text-align:center;border:1pxsolid#eeeeee;}
/**
* 组件的属性列表
*/properties:{//表格的列信息column:{type:Array},//表格的数据信息data:{type:Array}},
4. 页面中使用
"usingComponents":{"tabBox":"../../components/tabBox/tabBox","table":"../../components/table/table"},
{{country_active}}--{{goods_active}}<tabBoxdata-key="country_active"data="{{country_data}}"active="{{country_active}}"bind:change="$syncData"><viewstyle="text-align:center;color:red;padding:5rpx0">国家信息</view></tabBox><tabBoxdata-key="goods_active"data="{{goods_data}}"active="{{goods_active}}"bind:change="$syncData"><buttonstyle="width:200rpx">商品信息</button></tabBox><tablecolumn="{{table_column}}"data="{{table_data}}"></table><tablecolumn="{{column2}}"data="{{table2}}"></table>
/**
* 页面的初始数据
*/data:{//ajax请求,获取一份数据country_data:[{title:"中国",content:"中国的乒乓球很厉害"},{title:"美国",content:"中国的篮球很厉害"},{title:"日本",content:"中国的动漫很厉害"}],country_active:0,goods_data:[{title:"薯条",content:"薯条属于油炸食品,长期食用,可能会引发疾病"},{title:"饼干",content:"饼干很脆"},{title:"吐司",content:"吐司其实就是一种面包"}],
goods_active:1,//定义表格的列数据table_column:[{title:"学号",key:"no"},{title:"姓名",key:"name"},{title:"年龄",key:"age"},{title:"性别",key:"gender"}],//定义表单的数据table_data:[{no:"1001",name:"王俊凯",age:"22",gender:"男"},{no:"1002",name:"易烊千玺",age:"21",gender:"男",},{no:"1003",name:"王源",age:"22",gender:"男",}],column2:[{title:"城市",key:"city",},{title:"地址",key:"address"}],table2:[{city:"北京",address:"长安街108号"},{city:"上海",address:"南京路108号"}]}
八、ECharts
1. 引入ECharts
第一步:下载ecomfe/echarts-for-weixin 项目
第二步:拷贝 ec-canvas 目录
第三步:
"usingComponents":{"ec-canvas":"../../components/ec-canvas/ec-canvas"}
2. 在页面中使用ECharts
<viewclass="container"><ec-canvasid="mychart-dom-line"canvas-id="mychart-line"ec="{{ ec }}"></ec-canvas></view>
.container{width:95vw;height:400rpx;border:1pxsolidred;margin:2pxauto;}ec-canvas{width:100%;height:100%;}
//导入echarts对象import*asechartsfrom'../../components/ec-canvas/echarts';//初始化echarts的方法functioninitChart(canvas,width,height,devicePixelRatio){//初始化echarts对象constchart=echarts.init(canvas,null,{width,height,devicePixelRatio});//在画布中设置echarts对象canvas.setChart(chart);//ajax请求,获取一份数据letdata=[{year:'2015',cost:200,sale:400,},{year:'2016',cost:300,sale:500,},{year:'2017',cost:500,sale:400,},{year:'2018',cost:300,sale:400,},{year:'2019',cost:600,sale:700,},{year:'2020',cost:500,sale:400,}]//定义echarts的选项varoption={//标题/* title: {
//标题文本
text: '我的echarts图表',
//副标题
subtext:'2021-2-2',
//对齐方式
left: 'center'
}, *///颜色列表color:["#c04851","#2486b9","#10aec2","#5dbe8a"],// 图例组件/* legend: {
data: ['A', 'B', 'C'],
top: 50,
left: 'center',
backgroundColor: 'red',
z: 100
}, */// 设置边距grid:{top:10,left:10,right:20,bottom:10,//是否包含LabelcontainLabel:true},//提示框tooltip:{show:true,trigger:'axis',//格式化提示框formatter:function(val){letstr=" "+val[0].name+" 年";val.forEach(({seriesName,value,seriesIndex})=>{str+=`\n{marker${seriesIndex}at0|} `+seriesName+":"+value+" 万元";})returnstr}},//X轴xAxis:{type:'category',boundaryGap:false,//X轴的数据// data: ['2015','2016','2017','2018','2019','2020'],data:data.map(r=>r.year)// show: false},//y轴yAxis:{x:'center',type:'value',//分隔线splitLine:{//分隔线类型lineStyle:{type:'dashed'//虚线}}// show: false},//系列series:[{name:'成本',//类型:line,bar,pietype:'line',// 设置面积折线图样式// areaStyle:{},//润滑曲线smooth:true,//系列数据// data: [18, 36, 65, 30, 78, 40, 33]data:data.map(r=>r.cost)},{name:'销售',type:'line',smooth:true,// areaStyle:{},// data: [12, 50, 51, 35, 70, 30, 20]data:data.map(r=>r.sale)}]};//设置echarts的选项chart.setOption(option);//返回echarts对象returnchart;}Page({/**
* 页面的初始数据
*/data:{//定义页面中渲染的数据ec:{onInit:initChart}},/**
* 生命周期函数--监听页面加载
*/onLoad:function(options){},})
3. ECharts配合选择器
<van-fieldvalue="{{ value }}"placeholder="请选择城市"border="{{ true }}"bindtap="showPopup"readonly/><viewclass="container"><ec-canvasid="mychart-dom-line"canvas-id="mychart-line"ec="{{ ec }}"></ec-canvas></view><van-popupshow="{{ show }}"bind:close="onClose"position="bottom"><van-pickershow-toolbartitle="请选择城市"columns="{{ columns }}"bind:cancel="onClose"bind:confirm="onConfirm"/></van-popup>
//导入echarts对象import*asechartsfrom'../../components/ec-canvas/echarts';//定义echarts对象letchart=nullPage({//选择器确定按钮点击方法onConfirm(event){const{value}=event.detail;this.setData({value,show:false})//调用设置echarts选项的方法this.setChartOptions(value)},//显示弹出层showPopup(){this.setData({show:true});},//关闭弹出层onClose(){this.setData({show:false});},/** * 页面的初始数据
*/data:{//获取的城市名称value:'北京',//选择器显示的数据columns:['北京','上海','深圳','广州','成都','重庆','南京','杭州'],//设置弹出层是否显示show:false,//定义页面中渲染的数据ec:null},/**
* 生命周期函数--监听页面加载
*/onLoad:function(options){this.setData({//页面加载时,给ec赋值ec:{//初始化echarts的方法onInit:(canvas,width,height,devicePixelRatio)=>{//初始化echarts对象chart=echarts.init(canvas,null,{width,height,devicePixelRatio});//在画布中设置echarts对象canvas.setChart(chart);//调用设置echarts选项的方法this.setChartOptions('默认城市')//返回echarts对象returnchart;}}})},//设置echarts选项的方法setChartOptions(val){//根据val的值,发送ajax请求,获取对应的数据letdata=[{year:'2015',cost:Math.random()*200,sale:Math.random()*400,},{year:'2016',cost:Math.random()*300,sale:Math.random()*500,},{year:'2017',cost:Math.random()*500,sale:Math.random()*400,},{year:'2018',cost:Math.random()*300,sale:Math.random()*400,},{year:'2019',cost:Math.random()*600,sale:Math.random()*700,},{year:'2020',cost:Math.random()*500,sale:Math.random()*400,}]//定义echarts的选项varoption={//颜色列表color:["#c04851","#2486b9","#10aec2","#5dbe8a"],// 设置边距grid:{top:10,left:10,right:20,bottom:10,//是否包含LabelcontainLabel:true},//提示框tooltip:{show:true,trigger:'axis',//格式化提示框formatter:function(val){letstr=" "+val[0].name+" 年";val.forEach(({seriesName,value,seriesIndex})=>{str+=`\n{marker${seriesIndex}at0|} `+seriesName+":"+value+" 万元";})returnstr}},//X轴xAxis:{type:'category',boundaryGap:false,//X轴的数据data:data.map(r=>r.year)},//y轴yAxis:{x:'center',type:'value',//分隔线splitLine:{//分隔线类型lineStyle:{type:'dashed'//虚线}}// show: false},//系列series:[{name:'成本',type:'line',//润滑曲线smooth:true,//系列数据data:data.map(r=>r.cost)},{name:'销售',type:'line',smooth:true,data:data.map(r=>r.sale)}]};//设置echarts的选项chart.setOption(option);}})
九、位置API
1. 页面
<van-fieldtitle-width="80rpx"model:value="{{ address }}"centerclearablelabel="位置"placeholder="请输入位置"border="{{ true }}"type="textarea"autosize><van-buttonwx:if="{{show}}"bindtap="choose"icon="location-o"slot="button"size="small"type="primary"></van-button><van-buttonwx:elsebindtap="choose1"icon="location-o"slot="button"size="small"type="primary"></van-button></van-field><van-fieldtitle-width="80rpx"model:value="{{ address2 }}"centerclearablelabel="位置"placeholder="请输入位置"border="{{ true }}"type="textarea"autosize><van-buttonbindtap="choose2"icon="location-o"slot="button"size="small"type="primary"></van-button></van-field>
2. 后台
//选择方法choose(){//获取当前位置/* wx.getLocation({
success:({latitude,longitude})=>{
console.log(latitude,longitude);
}
}) *///选择位置wx.chooseLocation({//成功后的回调success:({address,name})=>{this.setData({address:address+' '+name})},//失败后的回调fail:({errMsg})=>{if(errMsg==="chooseLocation:fail auth deny"){this.setData({show:false})}// wx.$msg('通过右上角设置权限',2000,'none')}})},//该方法,用于打开设置界面choose1(){//打开设置界面wx.openSetting({success:({authSetting})=>{//判断是否勾选了获取用户位置权限if(authSetting['scope.userLocation']){this.setData({show:true})//直接调用选择位置方法this.choose()}}})},choose2(){//获取用户的当前设置wx.getSetting({//返回权限设置success:({authSetting})=>{//判断用户,如果拒绝过获取位置权限,打开设置界面if(authSetting['scope.userLocation']===false){//打开设置界面wx.openSetting({success:({authSetting})=>{//判断用户,如果勾选了获取位置权限,打开选择位置界面if(authSetting['scope.userLocation']===true){//打开选择位置界面wx.chooseLocation({//成功后的回调success:({address,name})=>{this.setData({address2:address+' '+name})},})}}})}else{//authSetting['scope.userLocation'] 返回 undefined 或 true 时执行 else//打开选择位置界面wx.chooseLocation({//成功后的回调success:({address,name})=>{this.setData({address2:address+' '+name})},})}}})},asyncchoose2(){letres=awaitwx.$chooseLocationWithSetting();this.setData({address2:res})},
3. location.js
//选择位置的方法exportlet$chooseLocation=()=>{returnnewPromise((resolve,reject)=>{//打开选择位置界面wx.chooseLocation({//成功后的回调success:({address,name})=>{resolve(address+' '+name)},})})}
//打开设置的方法exportlet$openSetting=()=>{returnnewPromise((resolve,reject)=>{//打开设置界面wx.openSetting({success:async({authSetting})=>{//判断用户,如果勾选了获取位置权限,打开选择位置界面if(authSetting['scope.userLocation']===true){resolve()}}})})}//通过设置选择位置的方法exportlet$chooseLocationWithSetting=()=>{returnnewPromise((resolve,reject)=>{//获取用户的当前设置wx.getSetting({//返回权限设置success:async({authSetting})=>{//判断用户,如果拒绝过获取位置权限,打开设置界面if(authSetting['scope.userLocation']===false){//先打开设置await$openSetting()//再获取位置信息letres=await$chooseLocation()resolve(res)}else{//获取位置信息letres=await$chooseLocation()resolve(res)}}})})}//将位置相关的方法,注册给微信对象wx.$chooseLocation=$chooseLocationwx.$openSetting=$openSettingwx.$chooseLocationWithSetting=$chooseLocationWithSetting
十、购物车案例
1. 页面
<viewclass="container"><viewclass="item flex j-s a-c"wx:for="{{goodslist}}"wx:key="index"><view><icondata-id="{{item.id}}"bindtap="check"class="ck iconfont {{item.ischecked?'iconfuxuankuang_xuanzhong1':'iconfuxuankuang_xuanzhong'}}"></icon></view><view><imageclass="img"src="{{item.img}}"/></view><viewclass="content"><viewclass="title">{{item.name}}</view><viewclass="price">¥{{item.price}}</view></view><counterdata-id="{{item.id}}"bind:change="change"count="{{item.count}}"></counter></view></view><viewclass="total flex j-s"><view><iconbindtap="checkAll"class="ck iconfont {{isCheckAll?'iconfuxuankuang_xuanzhong1':'iconfuxuankuang_xuanzhong'}}"></icon></view><viewclass="price">总计:¥{{total}}</view></view>
2. 样式
@import'../../assets/iconfont/iconfont.wxss';page{background:#eeeeee;}.container{padding:010rpx;margin-bottom:100rpx;}.item{width:98%;margin:10rpxauto;background:#ffffff;padding:10rpx20rpx;box-sizing:border-box;}.ck{font-size:40rpx;color:#248067;}.img{width:200rpx;height:200rpx;margin:010rpx;}.content{flex:1;}.contentview{margin:10rpx;}.title{color:#248067;font-weight:bold;}.price{color:#f1939c}.total{width:100%;padding:20rpx40rpx;box-sizing:border-box;position:fixed;left:0;right:0;bottom:0;background:#ffffff;}
3. 后台
//导入Mock对象importMockfrom'mockjs'//直接使用Mock对象随机生成一份数据letmockData=Mock.mock({'goodslist|4-10':[{'id|+1':1001,name:'@ctitle(2,4)',img:'@image(100x100)',price:'@float(10,100,2,2)',count:'@natural(1,10)',ischecked:false}]})//单独使用Mock随机返回一个数据// console.log(Mock.Random.cname(2,4));//使用Mock对象拦截ajax请求,随机返回一份数据Mock.mock('http://baidu.com','get',function(){returnMock.mock({'goodslist|4-10':[{'id|+1':1001,name:'@ctitle(2,4)',img:'@image(100x100)',price:'@natural(10,100)',count:'@natural(1,10)',ischecked:false}]})})Page({//计算总价的方法totalPrice(){lettotal=0//循环商品数组,累加消费总金额this.data.goodslist.filter(r=>r.ischecked).forEach(r=>{total+=r.price*r.count})//重新渲染页面this.setData({total:total.toFixed(2)})},//数量加减后调用的方法change(e){//获取对应商品的编号let{id}=wx.$key(e)//获取最新的数量letcount=e.detail//将最新的数量更新给对应的商品this.data.goodslist.find(r=>r.id===id).count=count;//调用计算总价的方法this.totalPrice()},//全选复选框选择方法checkAll(){//更新isCheckAll的状态this.data.isCheckAll=!this.data.isCheckAll//循环商品数组,更新所有商品的状态this.data.goodslist.forEach(r=>r.ischecked=this.data.isCheckAll)//重新渲染页面this.setData({isCheckAll:this.data.isCheckAll,goodslist:this.data.goodslist})//调用计算总价的方法this.totalPrice()},//复选框选择方法check(e){//获取到idlet{id}=wx.$key(e)//根据id获取对应的商品letgoods=this.data.goodslist.find(r=>r.id===id)//商品的选中状态取反goods.ischecked=!goods.ischecked//每次判断,所有商品是否全部选中this.data.isCheckAll=this.data.goodslist.every(r=>r.ischecked)//重新渲染页面this.setData({goodslist:this.data.goodslist,isCheckAll:this.data.isCheckAll})//调用计算总价的方法this.totalPrice()},/**
* 页面的初始数据
*/data:{//是否全选isCheckAll:false,//总价total:(0).toFixed(2),//商品数组goodslist:[]/* goodslist:[{
id:1001,
name:'可比克',
img:'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=331839707,1109674904&fm=26&gp=0.jpg',
price:9,
count:5,
ischecked:false
},{
id:1002,
name:'乐事',
img:'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=681102179,4036489030&fm=26&gp=0.jpg',
price:8,
count:3,
ischecked:false
},{
id:1003,
name:'奥利奥',
img:'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4180506903,453032051&fm=26&gp=0.jpg',
price:6,
count:8,
ischecked:false
},{
id:1004,
name:'奶茶',
img:'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=4015669984,136058038&fm=26&gp=0.jpg',
price:20,
count:2,
ischecked:false
}] */},/**
* 生命周期函数--监听页面加载
*/onLoad:function(options){this.setData({goodslist:mockData.goodslist})},})