We developed an open source tool based on Git for technical practice tutorial writing, all our tuq community tutorials are written with this tool, welcome Star

If you want to quickly learn how to use it, please read our tutorial documentation

This article is written by a Tuture writer who is not authorized to use the Tuture writing tool. Tuture community will seriate its uni-App and cloud function development mini-program blog series. Thanks to the author for his excellent output and making our technology world a better place 😆

I’m sorry for delaying my second post for a week for personal reasons. I didn’t expect that there are friends supporting me. Thank you very much and I’m sorry. In the first article, a third-party style has been introduced to achieve the switch between theme and language; This paper mainly starts the page building and cloud function creation. The front-end code calls the cloud function through unicloud.callFunction () method. The cloud function can perform JS operation, read and write the cloud database (NoSQL), and directly return JSON data. Server environment installation, configuration, and security are completely out of the question.

Login screen

  • Our tool for uni-app development is HbuilderX, which is generated when you right-click in the Pages folder and create a new page called login/pages/login/login.vueJson file (the new file will be placed at the end of the Pages array)
Json {"path" : "pages/login/login", "style" : {}}Copy the code
  • Define page Background
If you want to define the global page background, define it in the global CSS file, and then add the style page {background: # 999; }Copy the code
  • Font size and margin directly use colorUI’s own style, your own style can be written in style
< span style = "box-sizing: border-box; color: RGB (51, 51, 51); line-height: 20px; font-size: 14px; white-space: normal; background-color: RGB (255,255,255); } .text-sm { font-size: 24upx; } .text-df { font-size: 28upx; } .text-lg { font-size: 32upx; } .text-xl { font-size: 36upx; }Copy the code
// The following code is in line 2999 of colorui/main.css. Margin-0 {margin: 0; } .margin-xs { margin: 10upx; } .margin-sm { margin: 20upx; } .margin { margin: 30upx; Margin-top: auto; margin-top: auto; margin-top: auto; } .margin-bottom-auto { margin-bottom: auto; } .margin-left-auto { margin-left: auto; } .margin-right-auto { margin-right: auto; }Copy the code
  • The page code is as follows (event binding @tap, mobile click, used later)
<view class="login">// global blending, internationalization, as done in section 1<view class="login-title text-white text-sl text-center">{{lang.login_title}}</view>
	<view class="form-wrapper flex flex-direction margin-0-auto">
		<view class="bg-white radius flex flex-direction align-center">
			<view class="login-form-title text-bold text-xl margin-top-xl margin-bottom-xl">{{lang.login_form_title}}</view>
			<view class="login-form-username border-3-ccc margin-top-xs margin-bottom-xl">
				<input v-model='form.username' class="w-100 h-100 text-center text-df" type="text" value="" :placeholder="lang.login_form_username_placeholder" />
			</view>
			<view class="login-form-password border-3-ccc margin-top-xs margin-bottom-xl">
				<input v-model="form.password" class="w-100 h-100 text-center text-df" type="password" value="" :placeholder="lang.login_form_password_placeholder" />
			</view>

			<button type="primary" @tap='login' class="cu-btn login-btn text-xl margin-top-sm" :class="['bg-' + themeColor.name]">{{lang.login_submit_btn}}</button>
			<view @tap='loginWithWechat' class="login-with-wechat text-df margin-top-sm text-center text-btn" :class="['text-'+themeColor.name]">
				{{lang.login_with_wechat}}
			</view>
		</view>

		<view @tap='register' class="login-with-wechat text-df margin-top-auto text-white text-center text-btn">
			{{lang.login_register}}
		</view>
	</view>
	<open-data type="userAvatarUrl"></open-data>
	<open-data type="userNickName"></open-data>
	<button type="default" @getuserinfo="getuserinfo" open-type="getUserInfo">getUserInfo</button>
</view>// If the SCSS plugin is not installed, click the Settings menu to install the plugin //. .login {.login-title {padding: 212rpx 0 50rpx 0; } .form-wrapper { width: 580rpx; height: 808rpx; .bg-white { height: 660rpx; .login-form-username { width: 400rpx; height: 88rpx; border-radius: 44rpx; overflow: hidden; } .login-form-password { @extend .login-form-username; } .login-btn { width: 400rpx; height: 88rpx; border-radius: 44rpx; }}}}Copy the code

Simple encapsulation operation

  • Create one in the root directory/utils/plugins.js, introduced in main.jsrequire('./utils/plugins.js')
  • Add vuex
// The following contents are in /utils/plugins.js
import Vue from 'vue'
import store from '.. /store';
// Stores in uni do not need to be registered in the new Vue of main.js
Vue.prototype.$store = store;
Copy the code
  • Encapsulate the Toast prompt box
// The following contents are in /utils/plugins.js
Vue.prototype.$toast = (title, duration = 1500) = > uni.showToast({
	icon: 'none',
	title,
	duration
})
Copy the code
  • Encapsulated routes jump navigateTo, switchTab, reLaunch
Vue.prototype.$router = (url) = > uni.navigateTo({
	url: '/pages' + url,
	animationType:"slide-in-left".// Jump animation
	animationDuration: 800
})
// Jump to the page corresponding to tabbar at the bottom
Vue.prototype.$switchTab = (url) = > uni.switchTab({
	url: '/pages' + url
})
// Close other pages and jump
Vue.prototype.$relaunch = (url) = > uni.reLaunch({
	url: '/pages' + url
})
Copy the code
  • Encapsulate the cloud function request document
Vue.prototype.$uniCloud = async (name, data) => {
	uni.showLoading()
	try{
		let res = await uniCloud.callFunction({
			name, // Cloud function name
			data // Transfer data
		})
		return res
	} catch(e) {
		return e
	} finally{
		uni.hideLoading()
	}
}
Copy the code

Request cloud function

We have a cloudfunctions-aliyun folder in our root directory. Right-click to create a cloudfunction named user, and the directory will generate user/index.js. This user is the name of the cloudfunction. Index.js contains the following contents:

'use strict';
// Operations on cloud databases must be await, async await
exports.main = async (event, context) => {
  //event indicates the data to be uploaded. {}
  console.log('event : ' + event)
  // Return data to the client
  return event
};
Copy the code

We have the function to operate on the cloud database, we need to have the cloud database, initialize our cloud database, create db_init.json file in cloudfunctions-aliyun (see), json format, because we are doing login registration, So create the user table (collection)

/ / the user table "user" : {" data ": / / / data, there are two fields, {" username" : "admin", "password" : "admin"}], "index" : [{// index "MgoKeySchema": {// index rule "MgoKeySchema": [{"Name": "Username ", // index Direction: "1", 1: ASC- ascending, -1: DESC- descending}], "MgoIsUnique": true}}]}}Copy the code

We have the cloud database and the operation function, so we need a place to store the —- service space (please refer to the official website for basic concept understanding).

  • Right-click the cloudfunctions-aliyun folder and create a cloud service space. The browser will open the Web console automatically and the service space will have a unique id. Modify the name of the identified service space.

  • Right-click the cloudfunctions-aliyun folder to select the cloud service space you created, right-click the user cloudfunction to upload and run; On the one hand, you can upload, on the other hand, you can detect whether there are errors in the function. Refresh the Web console, you can find that the upload is successful:

// Check whether the cloud function is correct the following code is in login.vue
async onLoad() {
  await this.$uniCloud('user', {name: 'uncertainty'})}// Remember our cloud function, which returns what it sends
Copy the code

  • Db_init. json file is used to initialize the cloud database, and the web console is used to initialize the cloud database.

The front-end request

// The following code is in login.vue
async login() {
	if (!this.form.openid) {
     // Not wechat login, check whether the input is correct
		if (!this.form.username || !this.form.password) {
			this.$toast('Please fill in the correct information')
			return}}else {
		this.form.username = ' '
		this.form.password = ' '
	}

	
  let res = await this.$uniCloud('user'.this.form)
	if (res.result.code === 0) {
		this.$toast('Successful landing')}else {
		this.$toast(res.result.msg)
	}
}
Copy the code
  • Enter the user name and password (you can write it yourself if necessary), click the login button, and check :(there is no successful login because there is no code)

Login cloud function

  • Common methods of collection

const db = uniCloud.database()
exports.main = async (event, context) => {
  // Get the collection object of the user table
  const collection = db.collection('user')
  let user
  Username = event.username; username = event.password
  user = await collection.where({
  	username: event.username,
  	password: event.password
  }).get()
  
  // affectedDocs as found number
  if (user.affectedDocs < 1) {
    // Not found
  	return {
  		code: - 1.msg: 'Wrong username or password'}}else {
  	return {
  		code: 0.msg: 'success'}}}Copy the code

Enter the initialized admin, admin. Success

Wechat OpenID login

  • Applet request
// The following code is in login.vue
loginWithWechat() {
    let _this = this
    uni.login({
      async success(res) {
        let result = await _this.$uniCloud('loginWithWechat', {
            js_code: res.code
          })

        _this.form.openid = result.result.data.openid
        _this.login()
      }
    })
},
Copy the code
  • Create a cloud function loginWithWechat
// The following code is in the cloud function loginWithWechat/index.js
exports.main = async (event, context) => {
   // Get the openID request address
	const apiUrl = 'https://api.weixin.qq.com/sns/jscode2session';
  // unicloud. httpClient initiates the request
	const res = await uniCloud.httpclient.request(apiUrl,
	{
		method: 'GET'.dataType:"json".data: {
			'grant_type' : 'authorization_code'.'appid'	  : ' '.// The appid of your own applet
			'secret'  : ' '.// In the Applets Management platform -> Development -> Development Settings
			'js_code' : event.js_code // wx.login gets the code}});// Return data to the client
	return res
};
Copy the code
  • We’ve got OpenID

Clicking the wechat login button will show the wrong user name or password, because we did not make a judgment in the user cloud function. Modify the user cloud function (click wechat login and find the login is successful)

// The following code is in the user cloud function index.js
const db = uniCloud.database()

exports.main = async (event, context) => {
  	const collection = db.collection('user')
  	let user
  	if (event.openid) {
  		user = await collection.where({
  			openid: event.openid
  		}).get()

  		if (user.affectedDocs < 1) {
  			// If not, add it
  			await collection.add({
  				openid: event.openid
  			})
  		}

  		return {
  			code: 0.msg: 'success'}}else {
  		user = await collection.where({
  			username: event.username,
  			password: event.password
  		}).get()

  		if (user.affectedDocs < 1) {
  			return {
  				code: - 1.msg: 'Wrong username or password'}}else {
  			return {
  				code: 0.msg: 'success'}}}};Copy the code
  • Mysql > select * from user; select * from user; select * from user;

The registration screen

  • Page layout here is not much to say, direct shuttle ha
// The following code is in register.vue<template>
	<view class="register">
		<cu-custom :bgColor="'bg-'+themeColor.name" :isBack="true">
			<block slot="backText">return</block>
			<block slot="content">registered</block>
		</cu-custom>
		<view class="register-title text-white text-sl text-center">{{lang.login_title}}</view>
		<view class="text-white text-sm text-center">{{lang.create_new_account}}</view>
		<view class="form-wrapper flex flex-direction margin-0-auto">
			<view class="flex flex-direction align-center">
				<view class="register-form-username border-3-white margin-top-xl margin-bottom-xl">
					<input v-model='form.username' class="w-100 h-100 text-center text-df text-white" type="text" value="" placeholder-class="register-placeholder-class text-white" :placeholder="lang.login_form_username_placeholder" />
				</view>
				<view class="register-form-password border-3-white margin-top-xs margin-bottom-xl padding-left-sm padding-right-sm">
					<input v-model="form.password" class="w-100 h-100 text-center text-df text-white" type="password" value="" placeholder-class="register-placeholder-class text-white" :placeholder="lang.login_form_password_placeholder" />
				</view>
				<view class="register-form-password border-3-white margin-top-xs margin-bottom-xl padding-left-sm padding-right-sm">
					<input v-model="form.confirm_password" class="w-100 h-100 text-center text-df text-white" type="password" value="" placeholder-class="register-placeholder-class text-white" :placeholder="lang.register_form_confirm_password_placeholder" />
					<text v-if='isConfirm' class="text-red wrong-confirm-password animation-fade">{{lang.register_wrong_confirm_password_tips}}</text>
				</view>

				<button type="primary" @tap='register' class="cu-btn register-btn text-xl margin-top-sm" :class="['bg-' + themeColor.name, 'light']">{{lang.register_submit_btn}}</button>
			</view>
			<view class="register-with-wechat text-df margin-top-auto text-white text-center text-btn">
				{{lang.register_policy}}
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				form: {
					username: ' '.password: ' '.confirm_password: ' '
				},
				isConfirm: false
			}
		},
		onLoad() {

		},
		watch: {'form.confirm_password'(val) {
				if(val && val ! = =this.form.password) {
					this.isConfirm = true
				} else if (val && val === this.form.password) {
					this.isConfirm = false}}},methods: {
			async register() {
				if (!this.form.username || !this.form.password || !this.form.confirm_password) {
					this.$toast('Please fill in the correct information')
					return
				}
				if (this.form.password ! = =this.form.confirm_password) {
					this.$toast(this.lang.register_wrong_confirm_password_tips)
					return
				}
                                // Here we use the original notation
				let res = await uniCloud.callFunction({
					name: 'user'.// Add a type to the index file to make it clear that the login type is get
					data: Object.assign({}, this.form, {
						type: 'add'})})if (res.result.code === 0) {
					this.$toast('Registration successful')
					/ / jump
					setTimeout((a)= >{
						uni.navigateBack()
					}, 1500)}else {
					this.$toast(res.result.msg)
				}
			}
		}
	}
</script>

<style lang="scss">page{ background: #999; } .register { .register-title { padding: 212rpx 0 20rpx 0; } .form-wrapper { .flex-direction { height: 660rpx; .register-form-username { width: 400rpx; height: 88rpx; border-radius: 44rpx; } .register-form-password { @extend .register-form-username; position: relative; .wrong-confirm-password{ position:absolute; top: 100%; left: 20rpx; } } .register-btn { width: 400rpx; height: 88rpx; border-radius: 44rpx; }}}}</style>
Copy the code
  • Modify the User cloud function
// The following code is in user/index.js
'use strict'; 
const { add } = require('./add/index.js') 
const { get } = require('./get/index.js')
// It feels like we should use enumeration for this file
// We use the global object as node
global.successMsg = 'success' 
global.successCode = 0 
global.wrongCode = - 1
 
exports.main = async (event, context) => { 
	switch (event.type) { 
		case 'add':
			return add(event) 
		case 'get':
        // Move the index code above to get/index.js
			return get(event) 
	}
};
Copy the code

Register cloud functions (ADD)

// The following code is in user/add/index.js
 
const db = uniCloud.database()

exports.add = async (data) => {
	const collection = db.collection('user')

	let user = await collection.where({
		username: data.username
	}).get() // Get ()
        
        // At a glance, the feeling need not explain
	if (user.affectedDocs < 1) {
		const res = await collection.add({
			username: data.username,
			password: data.password
		})
		return {
			code: global.successCode,
			msg: global.successMsg
		}
	} else {
		return {
			code: global.wrongCode,
			msg: 'Username duplicate, please re-enter'}}}Copy the code
  • After modifying the cloud function, remember to upload and run it. Registration is successful

Encrypted password

  • Check the Web side, we found that the data is in clear text, then we need to encrypt the password, the same is the user cloud function, we create a new user cloud functionutils/index.js, we use SHA1 encryption
// The following code is at utils/index.js
// Password encryption
function encodeUTF8(s) {
  var i, r = [], c, x;
  for (i = 0; i < s.length; i++)
    if ((c = s.charCodeAt(i)) < 0x80) r.push(c);
    else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x1F), 0x80 + (c & 0x3F));
    else {
      if ((x = c ^ 0xD800) > >10= =0) // Convert to Unicode for four-byte UTF-16
        c = (x << 10) + (s.charCodeAt(++i) ^ 0xDC00) + 0x10000,
          r.push(0xF0 + (c >> 18 & 0x7), 0x80 + (c >> 12 & 0x3F));
      else r.push(0xE0 + (c >> 12 & 0xF));
      r.push(0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
    };
  return r;
};

// The string is encrypted into the hex string
function sha1(s) {
  var data = new Uint8Array(encodeUTF8(s))
  var i, j, t;
  var l = ((data.length + 8) > > >6 << 4) + 16, s = new Uint8Array(l << 2);
  s.set(new Uint8Array(data.buffer)), s = new Uint32Array(s.buffer);
  for (t = new DataView(s.buffer), i = 0; i < l; i++)s[i] = t.getUint32(i << 2);
  s[data.length >> 2] | =0x80< < (24 - (data.length & 3) * 8);
  s[l - 1] = data.length << 3;
  var w = [], f = [
    function () { return m[1] & m[2] | ~m[1] & m[3]; },
    function () { return m[1] ^ m[2] ^ m[3]; },
    function () { return m[1] & m[2] | m[1] & m[3] | m[2] & m[3]; },
    function () { return m[1] ^ m[2] ^ m[3]; }
  ], rol = function (n, c) { return n << c | n >>> (32 - c); },
    k = [1518500249.1859775393.- 1894007588..- 899497514.],
    m = [1732584193.- 271733879..null.null.- 1009589776.];
  m[2] = ~m[0], m[3] = ~m[1];
  for (i = 0; i < s.length; i += 16) {
    var o = m.slice(0);
    for (j = 0; j < 80; j++)
      w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16].1),
        t = rol(m[0].5) + f[j / 20 | 0]() + m[4] + w[j] + k[j / 20 | 0] | 0,
        m[1] = rol(m[1].30), m.pop(), m.unshift(t);
    for (j = 0; j < 5; j++)m[j] = m[j] + o[j] | 0;
  };
  t = new DataView(new Uint32Array(m).buffer);
  for (var i = 0; i < 5; i++)m[i] = t.getUint32(i << 2);

  var hex = Array.prototype.map.call(new Uint8Array(new Uint32Array(m).buffer), function (e) {
    return (e < 16 ? "0" : "") + e.toString(16);
  }).join("");

  return hex;
};

module.exports = {
  sha1
}
Copy the code
  • Encrypt passwords at registration
// The following code is partially modified in user/add/index.js
const util = require('.. /utils/index.js')... const res =await collection.add({
	username: data.username,
	password: util.sha1(data.password) / / encryption
})
Copy the code
  • Decryption at login
// The following code is in user/get/index.js
const util = require('.. /utils/index.js')... user =await collection.where({
	username: data.username,
	password: util.sha1(data.password)
}).get()
Copy the code
  • Encryption success

  • Tencent cloud development friends, interested can try to use token authentication cloud token

At this point, the logics of login and registration are basically completed. When the cloud functions encounter problems, they will go to view the documents and use await to operate the cloud database. They can print and see the returned data format for logical judgment. I’m used to using code, but if you develop your own, you don’t need to use code, you can use try catch to capture the request logic. Cloud database operations can be directly configured on the Web side without using JSON files, which may be more convenient. When creating data on the Web side, the data must be in JSON format, and the _ID will be automatically added. If you add the _ID when creating data, the value provided by you will be used. When obtaining OpenID, keep secret well, do not disclose, pay attention to safe use.

Enter the page

What I have done above is to return to the login page to log in after successful registration. Friends can also directly enter the content page after successful registration. If necessary, you can store the login information locally so that you can remember the password and log in directly a second time. I am used to using VUex to read the state in the page, and vuex is also used to modify the cache. The first initialization directly assigns the value from the cache to the store object. Friends can choose.

Create bottom navigation

  • First add the tabBar field under pages. Json, and configure the bottom navigation to require at least two jumps. Click the bottom to jump to the page also need to create in the Pages directory, the corresponding button icon, I selected in ali’s font icon library link
Json "tabBar": {"color": "#666666", // text default color" selectedColor": "#1296DB", // text selectedColor" backgroundColor": "# FFFFFF", / / background color "list" : [{" pagePath ":" pages/home/home, / / click on the path of the jump "text", "story", / / at the bottom of the word "iconPath" : "Static/images/tabbar/story. PNG", / / the default icon "selectedIconPath" : "Static/images/tabbar story_active. PNG" / / selected icon}, {" pagePath ":" pages/gallery/gallery ", "text", "gallery", "iconPath" : "static/images/tabbar/gallery.png", "selectedIconPath": "static/images/tabbar/gallery_active.png" }, { "pagePath": "Pages/activities/activities", "text", "activity", "iconPath" : "static/images/tabbar/activities. PNG", "selectedIconPath" : "Static/images/tabbar activities_active. PNG"}, {" pagePath ":" pages/my/my ", "text", "my", "iconPath" : "static/images/tabbar/my.png", "selectedIconPath": "static/images/tabbar/my_active.png" } ] }Copy the code

After login, use this.$relaunch(‘/home/home’) or this.$switchTab(‘/home/home’) to jump to home.

Json. If you want to develop the home page layout, you can either move the home position to the first one or comment it out

  • Since the bottom navigation is a native configuration, the hierarchy is highest, which is why if you want to use a mask layer on a page, the following phenomenon occurs:

As you can see the mask layer does not cover the bottom navigation, we can hide the bottom navigation

// Triggered when clicking to pop up the mask
uni.hideTabBar()
// Hide mask layer is triggered
uni.showTabBar()
Copy the code
  • If you feel that the built-in bottom navigation style does not meet the UI design, you can customize the bottom navigation. Colorui provides several options for us:

  • Simply use the bottom navigation in ColorUI (layout the original project in ColorUIpages/component/bar.vueC)
// This style can be wrapped as a component and called where needed<view class="cu-bar tabbar bg-black" style="position: fixed; bottom: 0; left: 0; width:100%;">
	<view class="action text-green">
		<view class="cuIcon-homefill"></view>Home page</view>
	<view class="action text-gray">
		<view class="cuIcon-similar"></view>classification</view>
	<view class="action text-gray add-action">
		<button class="cu-btn cuIcon-add bg-green shadow"></button>release</view>
	<view class="action text-gray">
		<view class="cuIcon-cart">
			<view class="cu-tag badge">99</view>
		</view>The shopping cart</view>
	<view class="action text-gray">
		<view class="cuIcon-my">
			<view class="cu-tag badge"></view>
		</view>my</view>
</view>
Copy the code

Bottom navigation internationalization

Remember the little problem we left in the last section, the Chinese and English switching of the bottom navigation. Go back to switching languages in VUex

// The following code is in store/index.js
changeLang: function(state){
	uni.showActionSheet({
		itemList: ['Simplified Chinese'.'English'],
		success (e) {
			if(e.tapIndex === 0){
				lang = require('.. /language/zh.js')}else{
				lang = require('.. /language/en.js')}// Run vuex to modify the cache directly
			uni.setStorageSync("userLang", lang.langType)
			state.lang = lang;
			// Add the following code to tabbar
			uni.setTabBarItem({
				index:0.text: lang.home_stories
			})
			uni.setTabBarItem({
				index:3.text: lang.my})}})} uni.settabBarItem () Modifies the bottom navigation style, such as showing the number of chat messages, showing the red dot in the upper right corner, showing the numberCopy the code

The navigation bar

Remember that we are going to use the change theme, so the navigation bar is set to custom. Here we also use the notation provided by ColorUI to customize the top navigation bar.

  • First we register globally in main.js
// The following code is in main.js
import cuCustom from './colorui/components/cu-custom/cu-custom.vue'
Vue.component('cu-custom', cuCustom)
Copy the code
  • Page to introduce custom components
// The following code implements theme change with the // dynamic property in home.vue<cu-custom :bgColor="'bg-'+themeColor.name" :isBack="true">
    <block slot="content">{{lang.home_stories}}</block>
</cu-custom>
Copy the code

The interface style is as follows:

This is because we didn’t get the height of the navigation bar introduced in app.vue

// The following code is in app.vue
import Vue from 'vue'
// The onLaunch app will only be launched once
onLaunch: function() {
	console.log('App Launch')
        // Obtain system information
	uni.getSystemInfo({
		success: function(e) {
			// #ifndef MP
			Vue.prototype.StatusBar = e.statusBarHeight;

			// #ifdef MP-WEIXIN || MP-QQ
			Vue.prototype.StatusBar = e.statusBarHeight;
			let capsule = wx.getMenuButtonBoundingClientRect();
			if (capsule) {
				Vue.prototype.Custom = capsule;
				// Vue.prototype.capsuleSafe = uni.upx2px(750) - capsule.left + uni.upx2px(750) - capsule.right;
				Vue.prototype.CustomBar = capsule.bottom + capsule.top - e.statusBarHeight;
			} else {
				Vue.prototype.CustomBar = e.statusBarHeight + 50;
			}
                        // #endif}})}Copy the code
  • You can see that the navigation bar is working (you can switch the phone type in the mini program, including the bangs test effect), and the component code is incolorui/components/cu-custom.vueTo obtain the height of the system status bar when entering the application, assign the height to the custom view, and assign the title value to the slot value.

  • Put the code from the previous section into my page and introduce custom navigation bars
// Since the topic change was introduced in the last lesson, the code is directly used here, in /pages/my/my.vue<template>
	<view>
		<cu-custom :bgColor="'bg-'+themeColor.name" :isBack="true" :icon="'sort'">
			<block slot="content">{{lang.my}}</block>
		</cu-custom>

		<view class="cu-modal" :class="modalName=='RadioModal'? 'show':''" @tap="modalName =''">
			<view class="cu-dialog" @tap.stop="">
				<radio-group class="block" @change="RadioChange">
					<view class="cu-list menu text-left">
						<view class="cu-item" v-for="(item,index) in themeList" :key="index">
							<label class="flex justify-between align-center flex-sub">
								<view class="flex-sub flex">
									<view>{{item.title}}</view>
									<view :style="{backgroundColor: item.color}" style='height: 50rpx; width: 100rpx; margin-left: 30rpx; '></view>
								</view>
								<radio class="round" :class="radio=='radio' + index? 'checked':''" :checked="radio=='radio' + index? true:false"
								 :value="item.name"></radio>
							</label>
						</view>
					</view>
				</radio-group>
			</view>
		</view>

		<button class="btn" hover-class="navigator-hover" :class="['bg-' + themeColor.name]" @click='changeLang'>To switch between languages</button>
		<button class="btn" hover-class="navigator-hover" :class="['bg-' + themeColor.name]" @click='changeTheme' data-target="RadioModal">Change the topic</button>
	</view>
</template>

<script>
	import {ColorList} from './theme.js'
	export default {
		data() {
			return {
				radio: ' '.modalName: ' '.themeList: []}},methods: {
			changeLang(){
				this.$store.commit('changeLang')
			},
			changeTheme(e){
				this.themeList = []
				for (let i = 0; i<ColorList.length; i++) {let random = Math.floor(Math.random() * ColorList.length)
					let item = ColorList[random]
					this.themeList.indexOf(item) === - 1 && this.themeList.push(item)
					if (this.themeList.length > 5) break
				}
				this.modalName = e.currentTarget.dataset.target
			},
			RadioChange(e) {
				let name = e.detail.value
				let obj = this.themeList.filter(item= > {
					return item.name === name
				})
				this.$store.commit('setThemeColor', obj[0])
				this.modalName = ' '}}}</script>

<style>
button{
	margin-top: 20rpx;
}
</style>
Copy the code

  • If you don’t want to use a custom navigation bar, you can also use the built-in navigation bar API as follows
// Modify the title text
uni.setNavigationBarTitle({
    title: this.lang.title
});
// Change the background color
uni.setNavigationBarColor({
    frontColor: '#ffffff'.backgroundColor: '#ff0000'.animation: {
	duration: 400.timingFunc: 'easeIn'}})// It is convenient to use the native navigation bar. There is no need to worry about compatibility between different models
// You can check the official website for more navigation bar operations
// For more custom navigation styles, such as search, drop-down city, etc., check out the plugin marketplace
Copy the code
  • The languages on the page are as follows
// The following code is in language/en.js
module.exports = {
	// The langType attribute is the language package identifier. Do not delete it
	langType : 'en'.// login_page
	login_title: 'UBLOG'.login_form_title: 'LOGIN'.login_form_username_placeholder: 'please write your username'.login_form_password_placeholder: 'please write your password'.login_submit_btn: 'LOGIN'.login_with_wechat: 'LOGIN WITH WECHAT'.login_register: 'REGISTER'./ / register page
	create_new_account: 'CREATE NEW ACCOUNT'.register_submit_btn: 'SIGN UP'.register_form_confirm_password_placeholder: 'please confirm your password'.register_policy: 'Terms of Service and Privacy Policy'.register_wrong_confirm_password_tips: 'Password and Confirm Password inconsistent! './ / home page
	home_stories: 'STORIES'./ / to me
	my: 'MY'
}

// The following code is in language/ en.js
module.exports = {
	// The langType attribute is the language package identifier. Do not delete it
	langType : 'zh-CN'./ / landing page
	login_title: 'blog'.login_form_title: 'login'.login_form_username_placeholder: 'Please enter a user name'.login_form_password_placeholder: 'Please enter your password'.login_submit_btn: 'login'.login_with_wechat: 'wechat Login'.login_register: 'registered'./ / register page
	create_new_account: 'Create a new account'.register_submit_btn: 'registered'.register_form_confirm_password_placeholder: 'Confirm password'.register_policy: Terms of Service and Privacy.register_wrong_confirm_password_tips: 'Two different passwords'./ / home page
	home_stories: 'Your Story'./ / to me
	my: 'I'
}
Copy the code

In the next section, let’s go into the making of the home page and use it in combination with other plug-ins. If there is something wrong in the article, I hope you can correct it and put forward some good suggestions. The ability is general, the level is limited, if the article is helpful to you, feel gratified. I am not sure, thank you for reading!

Want to learn more exciting practical skills tutorial? Come and visit the Tooquine community.

If you think we did a good job, please like ❤️ ❤️