# dom

For those native functions that do not depend on UI interaction, nvue encapsulates them into modules, which is a method of calling native capabilities through javascript.

  • uni-app has built-in integrated native modules by default, such as BindingX, animation, DOM.addRule, etc. Introduce native App plug-ins through uni.requireNativePlugin
// Usage mode
	// PluginName is the native plugin name.
	const PluginName = uni.requireNativePlugin(PluginName);
  • Third-party native plug-ins that support native cloud packaging in the project nativeplugins directory and plug-in market. It is also very convenient for you to transplant the existing native modules to nvue platform. Usage: can only be used in manifest.json->App native plug-in configuration-> select local plug-in or cloud plug-in-> package the custom base. See details

  • nvue also supports js API interface of uni-app. Unless otherwise specified, it means that both vue file and nvue file support it. See details.

  • The uni-app API that is not supported in nvue, See details

# addRule

Weex provide the ability of loading custom through DOM.addRule. Developers can load iconfont and custom font by specifying the font-family. Developers may use the following code snippet to load their font:

	<template>
		<view>
			<text class="my-iconfont">&#xe85c;</text>	
		</view>
	</template>
	<script>
		export default{
			beforeCreate() {
				const domModule = uni.requireNativePlugin('dom')
				domModule.addRule('fontFace', {
					'fontFamily': "myIconfont",
					'src': "url('http://at.alicdn.com/t/font_2234252_v3hj1klw6k9.ttf')"
				});
			}
		}
	</script>
	<style>
		.my-iconfont {
			font-family:myIconfont;
			font-size:60rpx;
			color: #00AAFF;
		}
	</style>
	
	

addRule(type, contentObject)

  • @fontFace You should not change this as this is the name of the font rule
  • @fontFamily You should provide the name of your font-family there, the valid name should be a string.
  • @src The src of your custom font, and url('') is reserved for protocol reason, the supported parameters are listed below:
    • http. Read from http, e.g. url('http://at.alicdn.com/t/font_1469606063_76593.ttf')
    • https. Read from https, e.g. url('https://at.alicdn.com/t/font_1469606063_76593.ttf')
    • local, Android ONLY. Read from assets directory e.g. url('local://foo.ttf'), the foo.ttf is in your android assets directory.
    • file. Read from a local file, e.g. url('file://storage/emulated/0/Android/data/com.alibaba.weex/cache/http:__at.alicdncom_t_font_1469606063_76593.ttf')
    • data. Read from a base64 data source, e.g. url('data:font/truetype;charset=utf-8;base64,AAEAAAALAIAAAwAwR1NVQrD+....'), the above data field is only a part of the actual data.

Notice

You can name fontFamily in addRule as you wish in your page, any string is OK. But this is not the real font-family name of the font file. The real name or system name for the font is stored in binrary data of ttf file. You must ensure that the real font-family name of font file is unique. Or your font may not be successfully registered to device and your text may display as a '?'. Specially, if you are using http://www.iconfont.cn/ to build your iconfont. Make sure that you set a unique enough font-family name for your font in project settings. Calling addRule in beforeCreate is recommended.

# scrollToElement

Scroll the scrollable component to the referenced component. This API should only be used in the children components of a scrollable component, such as in a <scroller> or <list> component.

scrollToElement(ref, options)

  • @ref, the referenced component who is meant to scroll into the view.
  • @options
    • offset, an space on top of the ref component, which is also scrolling down to the visual viewport. Default is 0.
    • animated, a boolean indicates whether a scroll animation should be played. If set to false, the ref component will jump into the view without any transition animation. Default is true.
  <template>
    <view class="wrapper">
      <scroller class="scroller">
        <view class="row" v-for="(name, index) in rows" :ref="'item'+index">
          <text class="text" :ref="'text'+index">{{name}}</text>
        </view>
      </scroller>
      <view class="group">
        <text @click="goto10" class="button">Go to 10</text>
        <text @click="goto20" class="button">Go to 20</text>
      </view>
    </view>
  </template>
  <script>
    const dom = uni.requireNativePlugin('dom')
    export default {
      data() {
        return {
          rows: []
        }
      },
      created() {
        for (let i = 0; i < 30; i++) {
          this.rows.push('row ' + i)
        }
      },
      methods: {
        goto10(count) {
          const el = this.$refs.item10[0]
          dom.scrollToElement(el, {})
        },
        goto20(count) {
          const el = this.$refs.item20[0]
          dom.scrollToElement(el, {
            offset: 0
          })
        }
      }
    }
  </script>
  <style scoped>
    .scroller {
      width:700rpx;
      height:500px;
      border-width: 3px;
      border-style: solid;
      border-color: rgb(162, 217, 192);
      margin:0 25rpx;
    }
    .row {
      height: 100rpx;
      flex-direction: column;
      justify-content: center;
      padding-left: 30rpx;
      border-bottom-width: 2px;
      border-bottom-style: solid;
      border-bottom-color: #DDDDDD;
    }
    .text {
      font-size: 45rpx;
      color: #666666;
    }
    .group {
      flex-direction: row;
      justify-content: center;
      margin-top: 60rpx;
    }
    .button {
      width: 200rpx;
      padding-top: 20rpx;
      padding-bottom: 20rpx;
      font-size: 40rpx;
      margin-left: 30rpx;
      margin-right: 30rpx;
      text-align: center;
      color: #41B883;
      border-width: 2px;
      border-style: solid;
      border-color: rgb(162, 217, 192);
      background-color: rgba(162, 217, 192, 0.2);
    }
  </style>

# getComponentRect

You can get the bounding rect of the referenced component using this API.

getComponentRect(ref, callback)

  • @ref, the referenced component.
  • @callback, the callback function after executing this action.

An example callback result should be like:

  {
    result: true,
    size: {
        bottom: 60,
        height: 15,
        left: 0,
        right: 353,
        top: 45,
        width: 353
    }
  }

This method needs to be called after the node rendering to obtain the correct information, it can be called in mounted or updated after updating data

If you want to get the bounding rect of outside viewport of the weex container, you can specify the ref as a literal string 'viewport', like getComponentRect('viewport', callback).

# animation

The animation module is used to perform animation on components. JS-Animation can perform a series of simple transformations (position, size, rotation, background color, and opacity) on the component with Javascript.

For example, if you have a image component, you can move, rotate, grow, or shrink it by animation.

  <template>
    <view class="box">
      <view ref="test" @click="move" class="box-item"></view>
    </view>
  </template>
  <script>
      const animation = uni.requireNativePlugin('animation')
      export default {
          methods: {
              move() {
                  var testEl = this.$refs.test;
                  animation.transition(testEl, {
                      styles: {
                          backgroundColor: '#007AFF',
                          transform: 'translate(100px, 80px)',
                          transformOrigin: 'center center'
                      },
                      duration: 800, //ms
                      timingFunction: 'ease',
                      delay: 0 //ms
                  },()=>{
                      uni.showToast({
                          title: 'finished',
                          icon:'none'
                      });
                  })
              }
          }
      }
  </script>
  <style scoped>
    .box{
        width:750rpx;
        height:750rpx;
    }
    .box-item{
      width: 250rpx;
      height: 250rpx;
      background-color: #00aaff;
    }
  </style>

# transition

  • @ref, the element that will be animated. For example, if the value of ref for an element is test, you can start an animation with this.$refs.test.
  • @options, animation properties such as keys, duration.

The following table lists all legal parameters of options:

Property Describe
styles specifies the names and values of styles to which a transition effect should be applied.
duration specifies the duration of animation execution, the default value is 0, meaning that the component get the desired property immediately.
delay specifies the waiting time before the animation starts. The default value is 0.
needLayout Specifies whether the change to layout(width/height/etc..) is persistence and takes affect after the animation. Default value is false
timingFunction describes how the intermediate values are calculated for the CSS properties being affected by the animation effect. default value is linear

The supported styles are listed below:

Property Describe
width Indicate the width value applied to the component after the animation is executed. Set needLayout to true if you need to influence the layout. The default value is computed width.
height Indicate the height value applied to the component after the animation is executed. Set needLayout to true if you need to influence the layout. The default value is computed width.
backgroundColor The background color applied to the component after the animation is executed, the default value is computed backgroundColor.
opacity Indicate the opacity value applied to the component after the animation is executed, the default value is computed opacity.
transformOrigin transformOrigin defines the central point of the change process, such as transformOrigin: x-axis y-axis parameter x-axis can be left, center, right, length or percentage, and parameter y-axis can be top, center, bottom, length or percentage. The default value is center center.
transform The transformation type of transform may include rotate, translate, scale and other attributes. The default value is null. See details below

transform

Property Describe
translate/translateX/translateY Specify the location to which the element is to be moved. In length or percentage, and the default value is 0.
rotate/rotateX/rotateY v0.16+ specifies the angle at which the element will be rotated. In degree, and the default value is 0
scale/scaleX/scaleY Enlarge or reduce the element in proportion. In number, and the default value is 1
perspective v0.16+ the distance from the observer to the z=0 plane, which is valid in Android 4.1 and above. In number, and the default value is positive infinity.

timingFunction

Property Describe
linear The animation speed is the same from beginning to end
ease-in Animation speed from slow to fast
ease-out Animation speed from fast to slow
ease-in-out The animation first accelerates to the middle point and then decelerates to the end point
cubic-bezier(x1, y1, x2, y2) Define the change process in cubic Bessel function, and the parameter value of the function must be between 0 and 1. For more information about cubic bezier, please refer to cubic-bezier and Bézier curve.
  • @callback, callback is a function called after the completion of animation. In iOS platform, you can use function to get information of animation execution.

Notes

  • On iOS platform you can get animation's message about completion, there are two types of parameters with result, is Successand Fail, Android can not support until now.
  • Android doesn't support the result parameter.

If you need to use CSS animation, please refer to transition and transform.

# Using BindingX in nvue

uni-app is the separation of the logical layer and the view layer. At this point, two layers of communication costs will be incurred. Dragging elements in the view layer, for example, might not be a smooth experience due to communication loss if events are constantly received in the logic layer.

BindingX (opens new window) is a pre-description interaction syntax provided by weex. Analyze the BindingX rule by native, and handle the interaction and dynamic effect of the view layer according to this rule. No more real-time de-js logic layer running and communicating.

BindingX is similar to an enhanced version of css, with high running performance, but not as much programming flexibility as js.

uni-app has built-in BindingX, which can be used in nvue to complete complex animation effects.

  • From HBuilderX 2.3.4+, the uni-app compilation mode can directly reference the uni.requireNativePlugin('bindingx') module, and the weex mode also needs to use npm to reference.

  • For the BindingX demo example, please refer to the related examples of vue in the BindingX example, and copy the vue code in the experimental field to the nvue file.

# Notice
  • Don not use origin in expression for now
# Code example:
	<template>
	    <div class="container">
	        <div ref="b1" class="btn" style="background-color:#6A1B9A" @click="clickBtn">
	            <text class="text">A</text>
	        </div>
	        <div ref="b2" class="btn" style="background-color:#0277BD" @click="clickBtn">
	            <text class="text">B</text>
	        </div>
	        <div ref="b3" class="btn" style="background-color:#FF9800" @click="clickBtn">
	            <text class="text">C</text>
	        </div>
	        <div ref="main_btn" class="btn" @click="clickBtn">
	            <image class="image" ref="main_image" src="https://gw.alicdn.com/tfs/TB1PZ25antYBeNjy1XdXXXXyVXa-128-128.png" />
	        </div>
	    </div>
	</template>
	<script>
	    const Binding = uni.requireNativePlugin('bindingx');
	    module.exports = {
	        data() {
	            return {
	                isExpanded: false
	            }
	        },
	        methods: {
	            getEl: function(el) {
	                if (typeof el === 'string' || typeof el === 'number') return el;
	                if (WXEnvironment) {
	                    return el.ref;
	                } else {
	                    return el instanceof HTMLElement ? el : el.$el;
	                }
	            },
	            collapse: function() {
	                let main_btn = this.getEl(this.$refs.main_btn);
	                let main_image = this.getEl(this.$refs.main_image);
	                let b1 = this.getEl(this.$refs.b1);
	                let b2 = this.getEl(this.$refs.b2);
	                let b3 = this.getEl(this.$refs.b3);
	                let main_binding = Binding.bind({
	                    eventType: 'timing',
	                    exitExpression: 't>800',
	                    props: [{
	                        element: main_image,
	                        property: 'transform.rotateZ',
	                        expression: 'easeOutQuint(t,45,0-45,800)'
	
	                    }, {
	                        element: main_btn,
	                        property: 'background-color',
	                        expression: "evaluateColor('#607D8B','#ff0000',min(t,800)/800)"
	                    }]
	                }, function(res) {
	                    if (res.state === 'exit') {
	                        Binding.unbind({
	                            token: main_binding.token,
	                          eventType: 'timing'
	                        })
	                    }
	                });
	                let btn_binding = Binding.bind({
	                    eventType: 'timing',
	                    exitExpression: 't>800',
	                    props: [{
	                        element: b1,
	                        property: 'transform.translateY',
	                        expression: "easeOutQuint(t,-150,150,800)"
	                    }, {
	                        element: b2,
	                        property: 'transform.translateY',
	                        expression: "t<=100?0:easeOutQuint(t-100,-300,300,700)"
	                    }, {
	                        element: b3,
	                        property: 'transform.translateY',
	                        expression: "t<=200?0:easeOutQuint(t-200,-450,450,600)"
	                    }]
	                }, function(res) {
	                    if (res.state === 'exit') {
	                        Binding.unbind({
	                            token: btn_binding.token,
	                          eventType: 'timing'
	                        })
	                    }
	                })
	            },
	            expand: function() {
	                let main_btn = this.getEl(this.$refs.main_btn);
	                let main_image = this.getEl(this.$refs.main_image);
	                let b1 = this.getEl(this.$refs.b1);
	                let b2 = this.getEl(this.$refs.b2);
	                let b3 = this.getEl(this.$refs.b3);
	                let main_binding = Binding.bind({
	                    eventType: 'timing',
	                    exitExpression: 't>100',
	                    props: [{
	                        element: main_image,
	                        property: 'transform.rotateZ',
	                        expression: 'linear(t,0,45,100)'
	                    }, {
	                        element: main_btn,
	                        property: 'background-color',
	                        expression: "evaluateColor('#ff0000','#607D8B',min(t,100)/100)"
	                    }]
	                }, function(res) {
	                    if (res.state === 'exit') {
	                        Binding.unbind({
	                            token: main_binding.token,
	                          eventType: 'timing'
	                        })
	                    }
	                });
	                let btn_binding = Binding.bind({
	                    eventType: 'timing',
	                    exitExpression: 't>800',
	                    props: [{
	                        element: b1,
	                        property: 'transform.translateY',
	                        expression: "easeOutBounce(t,0,0-150,800)"
	                    }, {
	                        element: b2,
	                        property: 'transform.translateY',
	                        expression: "t<=100?0:easeOutBounce(t-100,0,0-300,700)"
	                    }, {
	                        element: b3,
	                        property: 'transform.translateY',
	                        expression: "t<=200?0:easeOutBounce(t-200,0,0-450,600)"
	                    }]
	                }, function(res) {
	                    if (res.state === 'exit') {
	                        Binding.unbind({
	                            token: btn_binding.token,
	                          eventType: 'timing'
	                        })
	                    }
	                })
	            },
	            clickBtn: function(e) {
	                if (this.isExpanded) {
	                    this.collapse();
	                } else {
	                    this.expand();
	                }
	                this.isExpanded = !this.isExpanded;
	            }
	        }
	    }
	</script>
	<style>
	    .container {
	        flex: 1;
	    }
	    .image {
	        width: 60px;
	        height: 60px;
	    }
	    .text {
	        color: #ffffff;
	        font-size: 30px;
	    }
	    .btn {
	        width: 100px;
	        height: 100px;
	        background-color: #ff0000;
	        align-items: center;
	        justify-content: center;
	        position: absolute;
	        border-radius: 50px;
	        bottom: 25px;
	        right: 25px;
	    }
	</style>

# nvue and vue communicate with each other

In uni-app, nvue and vue pages can be mixed and used.

It is recommended to use uni.$on, uni.$emit for page communication. The old communication method is no longer recommended.

# Communication implementation method
	//Page for receiving information
	// $on(eventName, callback)  
	uni.$on('page-popup', (data) => {  
	    console.log('title: ' + data.title)
	    console.log('content: ' + data.content)
	})  
	
	//Page for sending information
	// $emit(eventName, data)  
	uni.$emit('page-popup', {  
	    title: 'I am title',  
	    content: 'I am content'  
	});

Note when using this page to communicate: use uni.$off to remove the event listener before unloading the page. Reference (opens new window)

# Step:
  1. Use uni.postMessage(data) to send data communication in nvue, and the data is in JSON format (the values of key-value pairs only support String).
  2. Use onUniNViewMessage in App.vue to listen.
# Code example:
	//test.nvue
	<template>
	    <view @click="test">
	        <text>Click the page to send data</text>
	    </view>
	</template>
	<script>
	    export default {
	        methods: {
	            test(e) {
	                uni.postMessage({test: "Data",value:"Data"});
	            }
	        }
	    }
	</script>
	//App.vue
	<script>
	    export default {
	        onUniNViewMessage:function(e){
				console.log("App.vue receive data")
				console.log(JSON.stringify(e.data))  
	        },
	        onLaunch: function() {
	            console.log('App Launch');
	        }
	    }
	</script>

# Variables and data shared between vue and nvue

In addition communication events, variables and storage can also be shared between vue and nvue pages. The scheme of sharing variables and data provided by uni-app is as follows:

  1. vuex: From HBuilderX 2.2.5+, nvue supports vuex. This is vue's official state management tool.

Note: Direct introduction of store is not supported, you can use auxiliary methods such as mapState, mapGetters, mapMutations or use this.$store

  1. uni.storage: -vue and nvue pages can use the same uni.storage for storage. This storage is persistent. For example, the login status can be saved here.
  2. globalData: The globalData mechanism is universal at all ends. Define globalData in the App.vue file as follows:
	<script>  
	    export default {  
	        globalData: {  
	            text: 'text'  
	        },  
	        onLaunch: function() {  
	            console.log('App Launch')  
	        },  
	        onShow: function() {  
	            console.log('App Show')  
	        },  
	        onHide: function() {  
	            console.log('App Hide')  
	        }  
	    }  
	</script>
  • The way to operate globalData in js is as follows: getApp().globalData.text = 'test'
  • If you need to bind the data of globalData to the page, you can perform variable reassignment during the onShow declaration cycle of the page.

# Unsupported uni-app API in nvue

nvue supports most uni-app APIs. The following only lists the APIs that are not currently supported.

# Animation
API Describe Solution
uni.createAnimation() Create an animation instance animation
# Scroll
API Describe Solution
uni.pageScrollTo() Scroll the page to the target location scrollToElement
# Node layout interaction
API Describe
uni.createIntersectionObserver() Create and return an example of the IntersectionObserver object
# Painting

For the usage of canvas API, please refer to canvas document (opens new window).