小程序(三)

七、自定义组件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})},})

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容