百度小程序开发的基础

百度app下载:http://mo.baidu.com/

开发工具下载:https://smartprogram.baidu.com/docs/develop/devtools/history/

一、小程序全局配置App()

1、app.json

{
    // 设置页面路径的数组
    "pages": [
        "component/component",
        "api/api"
    ], 
    // 分包结构配置
    "subPackages": [
        {
            "root": "subpackage",
            "pages": [
                "pages/subpageone/subpageone",
                "pages/subpagetwo/subpagetwo"
            ]
        }
    ],
    // 设置页面展现
    "window": {
        // 导航栏标题文字内容
        "navigationBarTitleText": "Demo",
        // 导航栏背景色
        "navigationBarBackgroundColor": "#000000",
        // 导航栏标题颜色 balck/white
        "navigationBarTextStyle": "white",
        // 导航栏样式 default/custom
        "navigationStyle": "default",
        // 自定义导航栏custom的组件定义
        "usingComponents": {
            "nav-bar": "/components/navBar/navBar",
            "content": "/components/content/content"
        },
        // 背景颜色
        "backgroundColor": "#ffffff",
        // 下拉背景字体、loading图的样式 dark/light
        "backgroundTextStyle": "dark",
        // 顶部窗口的背景色 仅IOS支持
        "backgroundColorTop": "#ffffff",
        // 底部窗口的背景色 仅IOS支持
        "backgroundColorBottom": "#ffffff",
        // 是否开启下拉刷新
        "enablePullDownRefresh": "true",
        // 页面上拉触底事件时距页面底部距离(px)
        "onReachBottomDistance":"50",
        // 小程序页面是否禁止响应字体大小的设置 auto(响应)、none(不响应)
        "textSizeAdjust": "auto"
        // 小程序页面方向 portrait(默认为竖屏显示)、landscape(横屏显示)、auto(跟随系统方向显示)
        "pageOrientation": "auto"
    },
    // 分包预下载规则
    "preloadRule": {
       "pages/index": {
            "network": "all",
            "packages": ["subpackage"]
        }
    },
    // 底部tab栏的表现
    "tabBar": {
        // tab列表
        "list": [
            {
                "pagePath": "component/component",
                "text": "首页",
                "iconPath": "/images/API_normal.png",
                "selectedIconPath": "/images/API_selected.png"
            },
            {
                "pagePath": "api/api",
                "text": "详情",
                "iconPath": "/images/component_normal.png",
                "selectedIconPath": "/images/component_selected.png"
            }
        ],
        // tab背景色
        "backgroundColor" : "#ffffff",
        // tab边框颜色 white/black
        "borderStyle": "white",
        // tab上文字默认的颜色
        "color": "#000",
        // tab上文字选中颜色  
        "selectedColor": "#6495ED"
    },
    // 需要在后台使用的能力,如音乐播放
    "requiredBackgroundModes": ["audio"],
    // 网络超时
    "networkTimeout": {
        // request超时时间
        "request": 30000,
        // connectSocket超时时间
        "connectSocket": 10000,
        // uploadFile超时时间
        "uploadFile": 10000,
        // downloadFile超时时间
        "downloadFile": 10000
    },
    // 小程序权限相关设置
    "permission": {
        // 位置相关权限
        "scope.userLocation": {
            // 高速公路行驶持续后台定位
            "desc": "你的位置信息将用于小程序位置接口的效果展示" 
        }
    },
    // 自定义路由相关设置
    "routes": [
        {
            // 投放入口,scheme中的path
            "path": "home", 
            // 真实的物理存储路径
            "page": "pages/home/home" 
        }
    ],
    // 小程序cookie机制配置
    "cookie": {
        "enableStore": true
    }
}

2、app.js

App({
    /************** 生命周期函数 **************/
    // 监听Web态小程序登录成功:初次登陆成功触发(只会触发一次)
    onLogin: function (options) {
        // 仅在Web态小程序有效,App端是无效的
        // 使用 options.code 换取 session_key
    },
    // 监听小程序的初始化:小程序初始化完成触发(只会触发一次)
    onLaunch: function (options) {
        /* options的属性
         ** scene: 场景值
         ** path: 打开小程序的路径,
         ** query: 当前页面路径中的参数
         ** shareTicket: 标记转发对象
         ** referrerInfo: 从另一个小程序打开该小程序
         ** referrerInfo.appId: 来源小程序的AppKey
         ** referrerInfo.extraData: 来源小程序传过来的数据
        */
        console.log('SWAN launch');
    },
    // 监听小程序的显示:小程序初始化完成、从后台进入前台都会触发
    onShow: function () {
        console.log('SWAN展现');
    },
    // 监听小程序的隐藏:从前台进入后台触发
    onHide: function () {
        console.log('SWAN当前处于后台');
    },
    // 错误监听函数:发生脚本错误、API调用失败时触发
    onError: function () {
        console.log('SWAN发生错误');
    },
    // 页面不存在的监听函数:打开的页面不存在时触发
    onPageNotFound: function () {
        
    };
    // 全局变量
    globalData: 'SWAN'
});


// XXX.js
const appinfo = getApp();
console.log(appinfo.globalData);
// 上述写法不生效,可试试下述方法
Page({
    data: {
        appData: getApp().globalData
    },
    onShow() {
        console.log(this.data.appData);
    }
})

二、小程序页面Page()

1、四个文件

.css:样式文件

.js:控制交互逻辑的动态语言

Page({
    /************** 初始化数据 **************/
    data:{
        text: '百度小程序'id: 1,
        title: 'cs',
        price: '100'
    },
    
    
    
    
    /************** 生命周期函数 **************/
    // 页面初始化时触发(一个页面只会调用一次)
    onInit(param) {
        // param当前页面路径的参数
        // 不能进行任何依赖视图层的操作
        // 并非所有基础库都支持,兼容问题需考虑
        // 性能优化,建议将页面的数据网络请求放在 Page.onInit 中,并在网络请求的回调中执行 setData ,可以提升页面的加载速度。
    },
    // 页面加载时触发(一个页面只会调用一次)
    onLoad(param) {
        // param当前页面路径的参数
    },
    // 页面显示 / 切入前台时触发
    onShow() {},
    // 页面初次渲染完成时触发(一个页面只会调用一次)
    onReady() {},
    // 页面隐藏 / 切入后台时触发
    onHide() {},
    // 页面卸载时触发
    onUnload() {},
    
    
    
    
    /************** 页面事件处理函数 **************/
    // 监听该页面用户下拉刷新事件
    onPullDownRefresh() {
        // 需要在app.json的window选项中开启 enablePullDownRefresh
        // 如果需要单个页面支持下拉刷新,可以直接在页面目录下的 json 配置文件中开启enablePullDownRefresh
        // 当处理完数据刷新后,swan.stopPullDownRefresh可以停止当前页面的下拉刷新。
    },
    // 监听该页面用户上拉触底事件
    onReachBottom(e) {
        // 可以在 app.json 的 window 选项中或页面配置中设置触发距离 onReachBottomDistance 
        // 在触发距离内滑动期间,该事件只会被触发一次。
        console.log('onReachBottom');
        // 常见的业务场景是开发者在这里请求分页数据
    },
    // 监听用户滑动页面事件
    onPageScroll(e) {
        // e.scrollTop:页面在垂直方向已滚动的距离(单位:px)
        // 慎重调用此方法,避免在onPageScroll中过于频繁的执行setData等引起逻辑层-渲染层通信的操作
    },
    // 设置该页面的分享信息
    // 用户点击页面内的"分享"按钮(button 组件open-type="share")或者页面右上角菜单的"分享"按钮会调用
    // 此事件需要 return 一个Object,用于自定义分享内容。
    onShareAppMessage(e) {
        // e.from:分享事件来源。button:页面内转发按钮;menu:右上角分享菜单
        // e.target: 如果from值是button,则target是触发这次转发事件的button,否则为undefined
        return {
            // 分享标题
            title: this.data.title,
            // 分享内容(推荐设置为小程序简介或描述)
            content: '世界很复杂,百度更懂你——小程序简介或详细描述', 
            // 分享图标
            imageUrl: 'https://b.bdstatic.com/miniapp/images/bgt_icon.png',
            // 页面 path,必须是以/开头的完整路径。路径中的参数须通过encodeURIComponent进行编码。
            path: '/index/index',
             // 分享成功回调函数
            success(res) {},
            // 分享失败回调函数
            fail(err) {},
            // 分享结束(无论成功或失败)回调函数
            complete(res) {},
        };
    },
    // 点击 tab 时触发
    onTabItemTap(item) {
        // item.index: 被点击tabItem的序号,从 0 开始
        // item.pagePath: 被点击tabItem的页面路径
        // item.text: 被点击tabItem的按钮文字
    },
    // 监听页面 URL query 改变
    // 引起页面 URL query 更新的原因有:调用 swan.setURLQuery 
    onURLQueryChange({newURLQuery, oldURLQuery}) {
        console.log(newURLQuery, oldURLQuery); 
    },
    // 监听页面方向变化事件
    onResize(res) {
        /* res的属性
         ** orientation:当前页面方向 (竖屏: portrait、横屏: landscape)
         ** statusBarHeight:状态栏高度
         ** screenWidth:屏幕宽度
         ** screenHeight:屏幕高度
         ** windowWidth:窗口宽度
         ** windowHeight:窗口高度
         ** 
        */
    },
    
    
    
     /************** 组件事件处理函数 **************/
    // <view onTap="onTap"></view>
    onTap() {},
    
    
    // this.setData(data, callback)
    // this,setData({ id: 1 }, ()=> {});
    
    // getCurrentPages()
    // 全局函数用于获取当前页面栈的实例
    // 以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面
})

.swan:页面的展现模板

<!-- 基础数据绑定 -->
<view>{{test}}</view>
<!-- 循环 -->
<view s-for="p in persons">{{p.name}}</view>
<!-- 条件 -->
<view s-if="is4G">4G</view>
<view s-elif="isWifi">Wifi</view>
<view s-else>Other</view>
<!-- 事件 bind:事件名称 -->
<view class="view-more" bind:tap="loadMore">点击加载更多</view>
<!-- touchstart/touchmove/touchend/touchcancel/tap -->
<!-- dataset -->
<view data-swan="test" bind:tap="onTap"></view>
<!--touches Touch对象(文档、屏幕):pageX/pageY/clientX/clientY -->

.json:对本页面的窗口表现进行配置

{
  // 导航栏背景色
  "navigationBarBackgroundColor": "#ffffff",
  // 导航栏标题颜色 black/white
  "navigationBarTextStyle": "black",
  // 导航栏标题文件内容
  "navigationBarTitleText": "智能小程序接口功能演示",
  // 导航栏样式 custom/default
  "navigationStyle": "default",
  // 窗口背景色
  "backgroundColor": "#eeeeee",
  // 是否下拉刷新
  "enablePullDownRefresh": false,
  // 下拉loading样式 dark/light
  "backgroundTextStyle": "light",
  // 页面上拉触底事件触发时距离页面底部距离
  "onReachBottomDistance": 50,
  // 不允许页面上下滚动
  "disableScroll": false,
  // 页面方向
  "pageOrientation": "auto"
}

2、页面栈和路由

路由方式页面栈表现触发时期路由前页面路由后页面
初始化新页面入栈智能小程序打开的第一个页面onLoad, onShow
打开新页面新页面入栈调用 API swan.navigateTo 或使用组件 < navigator open-type=“navigateTo”/ >onHideonLoad, onShow
页面重定向当前页面出栈,新页面入栈调用 API swan.redirectTo 或使用组件 < navigator open-type=“redirectTo”/ >onUnloadonLoad, onShow
页面返回页面出栈调用 API swan.navigateBack 或使用组件 < navigator open-type=“navigateBack”/ > 或用户按左上角返回按钮onUnloadonShow
Tab 切换页面全部出栈,只留下初始的 Tab 页面调用 API swan.switchTab 或使用组件 < navigator open-type=“switchTab”/ > 或用户切换 Tab具体分析具体分析
重加载页面全部出栈,只留下新的页面调用 API swan.reLaunch 或使用组件 < navigator open-type=“reLaunch”/ >onUnloadonLoad, onShow

说明

  • navigateTo、redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar 。
  • reLaunch、redirectTo、navigateTo 可在需要跳转的应用内页面路径后带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔;如path?key=value&key2=value2,如果跳转的页面路径是 tabBar 页面则不能带参数。
  • 调用页面路由带的参数可以在目标页面的 onLoad、onShow 中获取

三、自定义组件Component()

1、创建自定义组件

一个自定义组件由 4 个文件 (.swan .css .js .json) 组成

.json文件

{
    "component": true
}

.swan文件

<view class="name" bindtap="tap">
    {{name}}{{age}}
</view>

.css文件

.name {
    color: red;
}

.js文件

Component({
    properties: {
        // 定义了name属性,可以在使用组件时,由外部传入。此变量可以直接在组件模板中使用
        name: {
            type: String,
            value: 'swan',
        }
    },
    data: {
        // 这里是一些组件内部数据
        age: 1
    },
    methods: {
        // 这里是一个自定义方法
        tap: function(){}
    }
})

页面在其json文件中引用,在swan中直接引用

// 页面json配置 home.json
{
    "usingComponents": {
        "custom": "/components/custom/custom"
    }
}
<!-- 页面模板 (home.swan) -->
<view>
    <!-- 在页面中对自定义组件进行引用 -->
    <custom name="swanapp"></custom>
</view>

2、组件模板(插槽slot)和组件样式

<!-- 1、组件模板 -->
<!-- 组件内部模板 -->
<view class="wrapper">
    <slot></slot>
    <view>组件内部节点</view>
    <slot name="slot1"></slot>
    <slot name="slot2"></slot>
</view>
<!-- 使用组件的页面或者组件 -->
<view>
    <custom-component>
        <view>这里是插入到组件slot中的内容</view>
        <view slot="slot1">我会被插入到组件上方</view>
        <view slot="slot2">我会被插入到组件下方</view>
    </custom-component>
</view>

<!-- 2、模板数据绑定(可以使用数据绑定,这样就可以向子组件的属性传递动态数据) -->
<!-- 组件内部模板 -->
<view class="component-range">
    <slot name="inner" var-name="name"></slot>
</view>
<!-- 使用组件的页面或者组件 -->
<view>
    <custom-component>
        <view>{{name}}</view>
    </custom-component>
</view>

<!-- 3、组件样式 -->
<!-- 组件内部模板 -->
<view class="external-class">这段文本的颜色由组件外的 class 决定</view>
<!-- 使用组件的页面或者组件 -->
<custom-component external-class="red-text" />

<!-- 3、全局样式类 -->
<!-- 组件内部模板 -->
<text class="global-class">这段文本的颜色由组件外的 class 决定</text>
// 组件内部模板
Component({
    // 组件样式
    externalClasses: ['external-class'],
    // 全局样式类
    options: {
        addGlobalClass: true,
    },
    data: {
        name: 'swan-inner'
    }
});
/* 使用组件的页面或者组件 */
.red-text {
    color: red;
}
.global-class {
    color: red;
}

3、Component构造器

// 自定义组件js
Component({
    // 组件的对外属性,是属性名到属性设置的映射表,属性设置中可包含三个字段, 
    // type 表示属性类型、
    // value 表示属性初始值、
    // observer 表示属性值被更改时的响应函数
    properties: {
        // 属性名
        propName: { 
            // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null
            type: String, 
            // 属性初始值(必填)
            value: 'val', 
            observer: function(newVal, oldVal) {
                // 属性被改变时执行的函数(可选)
            }
        }
    },
    // 监听指定字段的数据发生改变时触发
    observers: {
        'some.subfield': function(subfield) {
            // 使用 setData 设置 this.data.some.subfield 时触发
            // (除此以外,使用 setData 设置 this.data.some 也会触发)
            subfield === this.data.some.subfield
        },
        'some.field.**': function(field) {
            // 使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发
            // (除此以外,使用 setData 设置 this.data.some 也会触发)
            field === this.data.some.field
        },
        '**': function(value) {
            // 数据发生变化即触发,这里的 value 是 properties 和 data 的合集
        },
    }// 私有数据,可用于模板渲染
    data: {}, 
    
    // 类似于 mixins 和 traits 的组件间代码复用机制
    behaviors: [],
    // 组件接受的外部样式类
    externalClasses: [],
    // 一些选项
    options:{},
    // 组件生命周期声明对象,
    // 组件的生命周期:created、attached、ready、detached 将收归到 lifetimes 字段内进行声明,
    // 原有声明方式仍旧有效,如同时存在两种声明方式,则 lifetimes 字段内声明方式优先级最高
    lifetimes: {},
    // 组件所在页面的生命周期声明对象,目前仅支持页面的 show 和 hide 两个生命周期
    pageLifetimes: {},
    // 定义段过滤器,用于自定义组件扩展
    definitionFilter: {},
    

    // 生命周期函数:在页面初始化时执行
    onInit: function () {},
    // 生命周期函数:在组件实例刚刚被创建时执行,注意此时不能调用 setData
    created: function () {},
    // 生命周期函数: 在组件实例进入页面节点树时执行,可以为函数,或一个在methods段中定义的方法名
    attached: function () {},
    // 生命周期函数: 在组件布局完成后执行,此时可以获取节点信息
    ready: function () {},
    // 生命周期函数: 在组件实例被从页面节点树移除时执行
    detached: function () {},
    
    // 组件的方法,包括事件响应函数和任意的自定义方法
    methods: {
        onTap: function () {
            this.setData({
                // 更新属性和数据的方法与更新页面数据的方法类似
            });
        }
    },
});

组件的通用属性和方法

属性

  • is:组件的文件路径
  • id:节点id
  • dataset: 节点dataset
  • data: 组件数据,包括内部数据和属性值
  • properties:组件数据,包括内部数据和属性值(与 data 一致)

方法

  • setData(data, callback):设置 data 并执行视图层渲染
  • hasBehavior():检查组件是否具有 behavior(检查时会递归检查被直接或间接引入的所有 behavior)
  • triggerEvent():触发事件
  • createSelectorQuery():创建一个 SelectorQuery 对象,选择器选取范围为这个组件实例内,与 swan.createSelectorQuery().in(this) 是等效
  • createIntersectionObserver():创建一个 IntersectionObserver 对象,选择器选取范围为这个组件实例内
  • selectComponent():使用选择器选择组件实例节点,返回匹配到的第一个组件实例对象(会被 swan://component-export 影响),在生命周期 onReady 开始时生效
  • selectAllComponents():使用选择器选择组件实例节点,返回匹配到的全部组件实例对象组成的数组
  • groupSetData():立刻执行 callback ,其中的多个 setData 之间不会触发界面进行重复绘制

4、组件间的通信与事件

// 1、通过 dispatch 方法与父组件通信
/* 父组件逻辑 */
Component({
    messages: {
        'childmessage': function (e) {
            console.log('childmessage', e);
        }
    }
});
/* 子组件逻辑 */
Component({
    created() {
        this.dispatch('childmessage', {
            name: 'swan'
        });
    }
});

// 2、通过 triggerEvent 方法与父组件通信
/* 组件child逻辑 */
/* <button bindtap="onTap">点击这个按钮将触发 myevent 事件</button> */
Component({
    properties: {},
    methods: {
        onTap: function() {
            // detail对象,提供给事件监听函数
            var myEventDetail = {} 
            // 触发事件的选项 bubbles:是否冒泡  capturePhase:事件是否拥有捕获阶段
            var myEventOption = {bubbles:true} 
            this.triggerEvent('myevent', myEventDetail, myEventOption);
        }
    }
});
/* 使用该组件的页面 */
/* <child bindmyevent="listener"></child> */
Page({
    listener: function (e) {
        console.log(e);
    }
})

// 3、通过 this.selectComponent 方法获取子组件实例对象
<!-- 组件child页面 -->
<!-- <view>这是组件child</view> -->
<!-- 使用child的页面 -->
<!-- <child id="page-id">这是使用child</child> -->
// 使用该组件的逻辑
Page({
    onLoad: function () {
        const res = this.selectComponent('#page-id');
        console.log(res);
    }
});

5、抽象节点

自定义组件模板中的一些节点,其对应的自定义组件不是由自定义组件本身确定的,而是由自定义组件的调用者确定的。这时可以把这个节点声明为“抽象节点”。

例如,我们现在来实现一个“选框组”(selectable-group)组件,它其中可以放置单选框(custom-radio)或者复选框(custom-checkbox)

<!-- selectable-group.swan -->
<view s-for="{{labels}}">
    <label bindtap="itemTap" data-index="{{index}}">
        <selectable disabled="{{false}}" selected="{{selected[index]}}" name="{{name}}"></selectable>
        {{item}}
    </label>
</view>

<!--调用的组件或页面-->
<selectable-group generic:selectable="custom-radio" />
<selectable-group generic:selectable="custom-checkbox" />
<!-- selectable-group.json -->
{
    "componentGenerics": {
        "selectable": true,
        // 可放个默认组件
        "selectable": {
            "default": "path/to/default/component"
        }
    }
}

<!--调用的组件或页面d的json文件-->
{
    "usingComponents": {
        "custom-radio": "path/to/custom/radio",
        "custom-checkbox": "path/to/custom/checkbox"
    }
}

四、模板语法

1、模板语法

<!-- 基础数据绑定 -->
<!-- 双向绑定的数据需包裹在{= =} -->
<view>{{test}}</view>

<!-- 循环 -->
<view s-for="persons">{{index}}: {{item.name}}</view>
<view s-for="p,index in persons">{{index}}: {{p.name}}</view>
<view s-for="persons" s-for-index="idx" s-for-item="p">{{idx}}: {{p.name}}</view>
<!-- 如果列表中的项目会动态地增加、删除,并且希望列表中的项目保持自己的特征和状态(例如 input 中的输入内容),需要在 s-for 指令声明中指定 trackBy。 -->
<!-- trackBy 后跟的值可以是 s-for 的 array 中 item 本身或者其属性(如 item.id),该值需要是列表中唯一的字符串或数字,且不能动态改变。 -->
<!-- 当数据更新触发重新渲染时,将自动跟踪项的变更,原先列表内的项位置会移动,新添加的项会被渲染,以确保组件保持自身的状态,并且省去一部分重新渲染带来的消耗。 -->
<input s-for="list trackBy item" placeholder="请输入内容" />
<button bindtap="delete">删除首项</button>

<!-- 条件 -->
<view s-if="is4G">4G</view>
<view s-elif="isWifi">Wifi</view>
<view s-else>Other</view>

<!-- 模板 -->
<!-- template-demo.swan-->
<template name="person-card">
    <view>
        <text>位置: {{pos}}</text>
        <text>姓名: {{name}}</text>
    </view>
</template>
<!-- template-demo.swan-->
<template is="person-card" data="{{{...person}}}" />
<!-- template-demo.js -->
<!-- Page({ data: { person: { name: 'Lebron James', pos: 'SF', age: 33 } } }); -->

<!-- 事件处理 -->
<!-- 事件 bind:事件名称 -->
<view class="view-more" data-swan="test" bind:tap="loadMore">点击加载更多</view>
<!-- e.currentTarget.dataset.swan -->

/* 事件的分类
 ** tap: 触摸后马上离开
 ** longtap: 触摸后超过 350ms 再离开(推荐使用 longpress 事件代替)
 ** longpress: 触摸后超过 350ms 再离开,如果是指定了事件回调函数并触发了这个事件,tap 事件将不被触发
 ** touchstart: 触摸开始时
 ** touchmove: 触摸后移动时
 ** touchend: 触摸结束时
 ** touchcancel: 触摸后被打断时,如来电等
 ** touchforcechange: 支持 3D Touch 的 iPhone 设备,重按时会触发
 ** transitionend: 会在 transition 或 swan.createAnimation 动画结束后触发
 ** animationstart: 会在 animation 动画开始时触发
 ** animationiteration: 会在 animation 一次迭代结束时触发
 ** animationend: 会在 animation 动画完成时触发
*/

/* 事件绑定和冒泡 
 ** key以bind或catch开头,衔接事件类型,例如bindtapcatchtouchcancel。也可以在bind和catch后可以紧跟一个冒号,如bind:tap、catch:touchstart,其功能不变
 ** bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡
*/

/* 事件的捕获 
 ** 捕获阶段是位于冒泡阶段之前,在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反
 ** 在捕获阶段监听的方式是采用capture-bind、capture-catch关键字,后者将中断捕获阶段和取消冒泡阶段
 ** Tip:在安卓及开发者工具、Web 态特定浏览环境(早期浏览器),嵌套最内层元素 capture 与 bind 事件触发时机取决于模板中事件声明前后顺序,如果需要同时使用 capture 与 bind,需要保证其先后顺序避免导致触发顺序在不同平台不一致的问题。
*/

/* 事件对象
 ** type: 事件的类型
 ** timeStamp: 页面打开到触发事件所经过的毫秒数
 ** target: 触发事件的组件的属性值集合
 ** currentTarget: 当前组件的一些属性值集合
 ** detail: 自定义事件对象属性列表
 ** touches: 触摸事件类型存在,存放当前停留在屏幕中的触摸掉新增的数组
 ** changedTouches: 触摸事件类型存在,存放当前变化的触摸点信息的数组
 *** 扩展1:target/currentTarget
 **** dataset: 事件绑定的组件上由 data-开头的自定义属性组成的集合
 **** id: 事件绑定组件的id
 **** offsetTop: 元素向上偏移的像素值
 **** offsetLeft: 元素向下偏移的像素值
 *** 扩展2:detail
 **** 是自定义事件所携带的数据,具体详见组件定义中各个事件的定义。
 *** 扩展3:dataset
 **** 在组件的事件被触发时,也可以传递自定义的数据
 *** 扩展4:touch
 **** identifier: 触摸点的标识符
 **** clientX, clientY: 距离页面可显示区域(屏幕除去导航条)左上角的 X 轴与 Y 轴的距离
 **** pageX, pageY: 距离文档左上角的 X 轴与 Y 轴的距离
 *** 扩展5:changedTouch
 **** 数据格式同 touches,指的是有变化的触摸点,如 touchstart(开始),touchmove(变化),touchend,touchcancel(结束)等
*/

<!-- 文件的作用域 -->
/*
 ** 在JavaScript文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,且不会互相影响。
 ** 通过全局函数getApp()可以获取全局的应用实例,如果需要全局的数据可以在App()中设置
*/

<!-- 引用 -->
/* 1、import */
<!-- templateA.swan-->
<template name="A">
  <text> A template </text>
</template>
<!-- templateB.swan-->
<import src="../templateA/templateA.swan"/>
<template name="B">
  <text> B template </text>
</template>
<template is="A"/>
<!-- templateC.swan-->
<import src="../templateB/templateB.swan"/>
<template is="A"/>
<template is="B"/>
/* 2、include */
<!-- index.swan -->
<include src="header.swan"/>
<view> body </view>
<include src="footer.swan"/>
<!-- header.swan -->
<view> header </view>
<!-- footer.swan -->
<view> footer </view>

2、SJS语法参考

1)基础
  • 编写 SJS 逻辑
// pages/utils.sjs中编写SJS逻辑
const bar = function(name) {
    return 'swan-' + name;
}
const foo = 'hello swan';

export default {
    bar: bar,
    foo: foo
};
// 或者使用CMD的形式导出
// module.exports = {
//     bar: bar,
//     foo: foo
// };
  • 引用并调用 SJS
<!-- 在 pages/index/index 页面中 -->
<!-- 引用SJS -->
<import-sjs src="../utils.sjs" module="utils" />
<!-- 使用SJS -->
<view class="container">{{utils.bar(name)}}</view>
<view>{{utils.foo}}</view>
  • 页面显示结果
swan-sjs
hello swan
import-sjs 标签

相关属性:

module: 当前<import-sjs>标签的模块名。必填字段

src: 引用.sjs文件的路径,仅当本标签为单闭合标签或标签的内容为空时有效; 如果当做 sjs 代码容器标签,则不必填写。

注意:import-sjs标签除了引用其它sjs模块,还可直接作为SJS代码的容器,使用module制定该模块名称,用法与上等同。

<!-- 定义SJS -->
<import-sjs module="utils">
const bar = function(name) {
    return 'swan-' + name;
}
const foo = 'hello swan';

export default {
    bar: bar,
    foo: foo
};
</import-sjs>

<!-- 使用SJS -->
<view class="container">{{utils.bar(name)}}</view>
<view>{{utils.foo}}</view>
2)变量
  • SJS 中的变量均为值的引用;
  • 没有声明的变量直接赋值使用,会被定义为全局变量;
  • 如果只声明变量而不赋值,则默认值为undefined
  • var 表现与 javascript 一致,会有变量提升;
  • 支持 const 与 let,与 JavaScript 表现一致。
// 在SJS模块中
var count = 110;
var bar = 'hello swan';
// undef === undefined
var undef; 
const NAME = 'SJS';
let str = 'string';

变量命名必须符合下面两个规则:

  • 首字符必须是:字母(a-zA-Z),下划线(_)
  • 剩余字符可以是:字母(a-zA-Z),下划线(_), 数字(0-9)
3)注释
// pages/utils/sjs

// const NAME = 'sjs';

/**
 * let str = 'swan';
 */
4)运算符

与 javascript 一致

5)语句

与 javascript 一致

if语句、switch语句、for语句、while语句

6)数据类型

SJS语言目前共有以下几种数据类型:

  • number : 数值
  • boolean:布尔值
  • string :字符串
  • object:对象
  • function:函数
  • array : 数组
  • date:日期
  • regexp:正则
7)基础类库
  • console
  • Math
  • JSON
  • Number
  • Date
  • Global

方法

  • parseInt
  • parseFloat
  • isNaN
  • isFinite
  • decodeURI
  • decodeURIComponent
  • encodeURI
  • encodeURIComponent
8)esnext
  • let & const
  • 箭头函数
  • 更简洁的字面量
  • 模板字符串
  • 解构赋值
  • Default + Rest + Spread

3、Filter过滤器

推荐使用功能更全的 SJS 功能。Filter 功能将不再更新,请勿在s-ifs-fortemplate、自定义组件等标签中使用。
Filter 是小程序的过滤器,结合 SWAN 模板,可以构建出页面的结构。

说明
  • Filter 文件命名方式为:模块名 .filter.js ;
  • Filter 通过 export default 方式对外暴露其内部的私有函数;
  • Filter 只能导出 function 函数;
  • Filter 函数不能作为组件的事件回调;
  • Filter 可以创建独立得模块,也可以通过内联的形式;
  • Filter 不支持全局变量;
  • 多个 filter 标签不能出现相同的 src 属性值, module 属性的值也是标识模块的唯一 id 。
<!-- filter 内联渲染 -->
<!-- swan -->
<view> {{swan.message()}} </view>
<filter module="swan">
    export default {
        message: function() {
            return 'Hello world';
        }
    }
</filter>

<!-- 数据处理-->
<!-- swan模板 -->
<view>{{swan.maxin(array)}}</view>
<filter src="./index.filter.js" module="swan"></filter>
// index.js
Page({
    data: {
        array: [1, 3, 6, 8, 2, 0]
    }
});
// index.filter.js
export default {
    maxin: arr => {
        var max = undefined;
        for (var i = 0; i < arr.length; ++i) {
            max = max === undefined ?
            arr[i] :
            (max >= arr[i] ? max : arr[i]);
        }
        return max;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值