Notes on Vue2 and uni-app#
Vue2#
Vue allows the creation of reusable block tags through components. Most of the time, Vue components are written using a special syntax for HTML templates. When more control than what HTML syntax allows is needed, JSX or pure JavaScript functions can be written to define components. A Vue application consists of a root Vue instance created with new Vue
, along with an optional nested, reusable component tree.
The template is a top-level node used to write tag components, while script and style are parallel top-level nodes, meaning there are three top-level nodes.
-
HTML is a markup language used to structure our web content and give meaning to it, such as defining paragraphs, headings, and data tables, or embedding images and videos in the page.
-
CSS is a style sheet language that applies styles to HTML content, such as setting background colors and fonts, and laying out content in multiple columns.
-
JavaScript is a scripting language that can be used to create dynamically updating content, control multimedia, create animations, and much more.
DOM#
The Document Object Model (DOM) is an API (Application Programming Interface) for HTML and XML documents. The DOM connects web pages to scripts or programming languages by storing the structure of the document (such as the HTML representing the web page) in memory as objects. The DOM represents the document in the form of a logical tree. Each branch of the tree ends with a node, and each node contains an object. DOM methods allow programmatic access to the tree. With these methods, you can change the structure, style, or content of the document.
Directives#
Directives are special attributes prefixed with v-
. The value of a directive attribute is expected to be a single JavaScript expression (with v-for
being an exception).
<!-- Complete syntax -->
<a v-on:click="doSomething">...</a>
<!-- Shorthand -->
<a @click="doSomething">...</a>
<!-- Complete syntax -->
<a v-bind:href="url">...</a>
<!-- Shorthand -->
<a :href="url">...</a>
Computed Properties and Method Properties#
Computed properties are cached based on their reactive dependencies. They will only re-evaluate when their related reactive dependencies change. In contrast, calling a method will always execute the function again whenever a re-render is triggered. Therefore, computed properties are more efficient.
Meaning of Getter and Setter#
Getter#
- Meaning:
- A Getter is a primary component of computed properties; it is a function used to get the value of a computed property.
- When you access a computed property, you are actually calling the getter method.
- Usage:
- Getter methods are typically used to compute a new value based on other data properties.
- Getter methods can access all data and other computed properties of the component.
- When the dependent data changes, Vue.js automatically calls the getter method to update the computed property's value.
Setter#
- Meaning:
- A Setter is an optional part; it is also a function used to set the value of a computed property.
- When you try to change a read-only computed property, Vue.js automatically calls the setter method.
- Usage:
- Setter methods are typically used to update the values of other data properties rather than directly changing the computed property itself.
- When a computed property is assigned a value, Vue.js will call the setter method.
Arrow Function Expressions =>#
() => {
statements
}
param => {
statements
}
(param1, paramN) => {
statements
}
Arrow functions can be async by adding the async keyword before the expression.
async param => expression
async (param1, param2, ...paramN) => {
statements
}
Asynchronous Operations and Async/Await#
Promise#
A Promise is the foundation of asynchronous programming in modern JavaScript. It is an object returned by an asynchronous function that indicates the current state of the operation. When a Promise is returned to the caller, the operation is often not yet complete, but the Promise object provides methods to handle the eventual success or failure of the operation.
The elegance of Promise lies in that then()
itself also returns a Promise, which indicates the completion status of the asynchronous function called in then()
. This allows for chaining promises.
A promise can be in one of three states: pending, fulfilled, or rejected.
Async and Await#
Adding async
at the beginning of a function makes it an asynchronous function.
In uni-app, the underlying logic and principles of async
and await
are the same as in other JavaScript environments.
In the lifecycle of Vue components, there are some hook functions that are asynchronous, such as created and mounted. These hook functions allow you to perform asynchronous operations after the component is created or mounted to the DOM.
this.$api.common.login(this.loginForm).then(async res => { // async asynchronous arrow function removes the function keyword, using => to connect the parameter list and function body
if (res.code == 200) {
// Store token and account
this.saveToken(res.token);
this.saveAccount();
// Get user information
let profile = await this.getProfile(); // Wait for the asynchronous operation to complete
uni.$u.vuex('profile', profile);
// Redirect to the home page
uni.switchTab({
url: '/pages/tabBar/home/index'
});
An async
function is a special function that always returns a Promise. Even if you do not explicitly return a Promise, the async
function will return a resolved Promise with a value of undefined
.
The await
keyword can only be used inside async
functions. It is used to wait for the result of a Promise. When await
is used on a Promise, the JavaScript engine will pause the execution of the async
function until the Promise is resolved or rejected.
The underlying principles of async
and await
are based on Promises. Promises are one of the standard ways to handle asynchronous operations in JavaScript, and they have three states: pending, fulfilled, and rejected. A Promise object represents an asynchronous operation that may eventually complete or fail, along with the value upon completion or failure.
The await
keyword is used to wait for the result of a Promise. When you use the await
keyword inside an async
function, the JavaScript engine will pause the execution of the async
function until the Promise is resolved or rejected. If the Promise is resolved, the value of the await
expression will be the resolved value; if the Promise is rejected, the await
expression will throw an error, which can be handled using try...catch
.
Slots#
<!-- Render images based on different conditions -->
<u--image v-if="device.imgUrl" :src="device.imageUrl" radius="10" mode="aspectFill"
width="70" height="70">
<!-- Slot displays images shown during different states -->
<view slot="error" style="font-size: 12px;">Load failed</view>
<template v-slot:loading>
<u-loading-icon></u-loading-icon>
</template>
The HTML element is part of the web component technology suite; it is a placeholder inside a web component that you can fill with your own markup to create separate DOM trees and render them together.
The $ Symbol#
In Vue.js, the use of the $ symbol is primarily based on specific properties and methods of the Vue instance or Vue component instance. These properties and methods typically start with a $, distinguishing them from regular data properties, computed properties, methods, etc. These properties and methods starting with $ are often provided by the Vue framework itself to perform Vue-related operations or access the internal state of the Vue instance.
Usage of : in template#
The v-bind
attribute is called a directive. Directives are prefixed with v-
to indicate that they are special attributes provided by Vue.
Whether to add :
when setting parameters mainly depends on whether you are setting HTML attributes or Vue-specific directives. They apply special reactive behavior on the rendered DOM.
Cases where :
is not needed#
Static HTML attributes: When you write attributes directly on an element, such as <div id="app">
, here id="app"
is a static HTML attribute whose value is determined at compile time and does not change with data in the Vue instance.
Vue directives but not attribute bindings: For certain Vue directives like v-model
, v-if
, v-for
, etc., they are not used to bind HTML attributes but are Vue-specific template directives used for data binding, conditional rendering, list rendering, etc. These directives do not require a :
prefix because they are not bindings of HTML attributes.
Cases where :
is needed#
Dynamic HTML attribute binding: When you want to dynamically set the attributes of an HTML element based on data in the Vue instance, you need to use the v-bind
directive. To simplify, Vue allows the use of :
as a shorthand for v-bind
. For example, <div :id="dynamicId">
means that the value of the id
attribute will be bound to the dynamicId
data property in the Vue instance. If the value of dynamicId
changes, the id
attribute of <div>
will also update accordingly.
<!-- Complete syntax -->
<a v-on:click="doSomething">...</a>
<!-- Shorthand -->
<a @click="doSomething">...</a>
Dynamic binding and static binding have performance differences. Dynamic binding incurs some rendering overhead because Vue.js needs to monitor changes in the expression and perform reactive updates. Static binding does not have such performance overhead because they are static values.
Passwordless Login Related#
Read the token value from local storage and store it in the Vuex state manager for easy access to this token value where needed.
getToken () {
// Get token from local storage
this.token = uni.getStorageSync('token');
// Store token in vuex
uni.$u.vuex('vuex_token', this.token);
}
Differences Between Token, Session, and Cookie#
-
Security: Tokens are generally more secure than cookies because they contain encrypted signatures and can be designed not to persist. Cookies are stored on the client side and are more vulnerable to attacks.
-
Scalability: Token mechanisms are better suited for stateless architectures and distributed systems because they do not require the server to maintain session state.
-
Cross-Domain Issues: Tokens can easily solve cross-domain issues, while traditional session cookies are subject to the same-origin policy.
this.$refs.form#
this.$refs.form
is a reference pointing to the form element or component with ref="form"
in the template.
When using the ref
attribute in the template of a Vue component, Vue creates a corresponding property in the $refs
object of that component instance, and the value of that property is the corresponding child component instance or DOM element.
Note: The value of $refs
is undefined
before the component is rendered. Therefore, you cannot directly access $refs
in the created
hook; you should access it in the mounted
hook or later in the lifecycle.
Page Structure#
Page | uni-app Official Website (dcloud.net.cn)
A page has three root node tags:
- Template component area
<template>
- Script area
<script>
- Style area
<style>
In a vue file, template
, script
, and style
are at the same level. In vue2, the second-level nodes of template
can only have one node, typically continuing to write page components under a root view
. But in vue3, the template can have multiple second-level nodes, eliminating one level.
In the script area, developers should be cautious when writing code outside of export default {}
; there are two considerations here:
- It affects application performance. This part of the code executes when the application starts, not when the page loads. If the code here is too complex, it will affect the application's startup speed and consume more memory.
- It does not get reclaimed when the component or page closes. Outer static variables will not be reclaimed when the page closes. If necessary, you need to handle it manually, such as in the
beforeDestroy
ordestroyed
lifecycle hooks.
Export#
In ES6 (ECMAScript 6), both export
and export default
can be used to export variables (including constants), functions, classes, files, modules, etc., which can then be imported in other files or modules using the import variable (including constants)|function|class|filename|module name syntax for use. There can be multiple exports, but there can only be one export default.
Install#
In Vue.js, using const install = (Vue, vm) => { ... }
and export default { install }
is a common pattern to define and export Vue plugins. This method allows you to create a plugin that can be used in Vue applications.
The install
function typically takes two parameters:
Vue
: The Vue constructor, which can be used to extend Vue's prototype, register global components, directives, etc.vm
: An optional parameter, usually used to access the context of the Vue instance, but has been deprecated in Vue 3.
Within the function body, various operations can be performed to configure Vue or register custom behaviors. When you import this module elsewhere (like in main.js
), you can install this plugin using the Vue.use()
method.
Prototype#
In JavaScript, the prototype is a special mechanism used to implement inheritance and share properties and methods between objects. Every JavaScript object has an internal property [[[Prototype]]]
, which points to another object known as the prototype object. When trying to access a property or method of an object, if that object does not have the property or method, the JavaScript engine will look up the prototype chain until it finds the property or method. Java, as an object-oriented programming language, also has a concept similar to the prototype mechanism in JavaScript, but it uses class inheritance and interface implementation. Java does not have a direct equivalent to JavaScript's prototype
, but we can explore some mechanisms in Java that achieve similar functionality to some extent.
prototype
is a special property that exists on all function objects. When a function is created, it automatically gets a prototype
property. This prototype
property is an object that serves as the prototype for newly created objects. When you create an object using a constructor function, the newly created object inherits properties and methods from the prototype
object.
In Vue.js, you can leverage JavaScript's prototype mechanism to extend Vue's prototype so that all Vue instances can share certain properties and methods. This is typically done by adding properties or methods to Vue.prototype
.
Vue.prototype.$api = {
// Import modules
common,
scene,
group,
deviceUser,
deviceLog,
device,
deviceJob,
account,
energyConsumptionAnalysis
};
The above code adds a property named $api
to Vue's prototype and includes custom modules. After this, you can access these methods through $api
in any Vue instance.
this.$api.common.xxx() // Access custom methods
Props#
uni-app Official Website (dcloud.net.cn)
Component Basics | Vue.js (vuejs.org)
props
can be an array or an object used to receive data from parent components. Props can be declared and registered on child components, with the values of the declared parameters defined in the parent component. Updates to parent props flow down to child components but not in reverse. props
can be simple arrays or use objects as alternatives, allowing for advanced options such as type checking, custom validation, and setting default values.
Ref#
uni-app Official Website (dcloud.net.cn)
Used to register reference information for elements or child components, which will be registered on the parent component's $refs
object.
<!-- Index parent component page -->
<template>
<view>
<base-input ref="usernameInput"></base-input>
<button type="default" @click="getFocus">Get Focus</button>
</view>
</template>
<script>
export default {
methods:{
getFocus(){
// Call focus method through the defined ref of the component
this.$refs.usernameInput.focus()
}
}
}
</script>
Vuex#
Vuex is a state management pattern specifically developed for Vue.js applications. It adopts a centralized storage model to manage the state of all components in the application and ensures that state changes occur in a predictable manner according to specific rules.
Differences Between Vuex and Global Variables
vuex | Global Variables |
---|---|
Cannot directly change variables in the store; data is modified by a unified method | Can be modified arbitrarily |
Each component can reference its own Vuex variable name without interference | Global variables may cause naming pollution |
Solves communication issues between multiple components | Cross-page data sharing |
Suitable for medium to large projects with complex multi-module and business relationships | Suitable for demos or small projects |
The core of every Vuex
application is the store
, which contains most of the state (state
) in your application.
State management has five core concepts: state
, getter
, mutation
, action
, and module
.
Uni-app#
Page Lifecycle#
Each Vue instance goes through a series of initialization processes when created—such as setting up data listeners, compiling templates, mounting the instance to the DOM, and updating the DOM when data changes. During this process, some functions called lifecycle hooks are also executed.
Mounted#
Called after the component's DOM elements are mounted to the document DOM. In the code below, if a token is found, it directly redirects the page.
mounted () { // The mounted hook is called after the component's DOM elements are mounted (i.e., inserted into the document DOM).
this.getToken(); // Get local cached token
if (this.token != '' && this.token != null) {
// Redirect to home page
uni.switchTab({
url: '/pages/tabBar/home/index'
});
} else {
this.getCode();
this.getAccount();
}
},
onShow, onHide, onUnload#
Note that page visibility is an event that can be triggered repeatedly.
When page a is first entered, a's onShow will be triggered.
When a navigates to page b, a will trigger onHide, while b will trigger onShow.
However, when b is closed, b will trigger onUnload, and at this point, when a is displayed again, it will trigger onShow again.
In tabbar pages (those configured in pages.json), switching between different tab pages will trigger their respective onShow and onHide.
Create#
Called immediately after the instance is created.
onReady#
Listens for the initial rendering completion of the page and executes the written code; at this point, the component is fully mounted, and the DOM tree is available.
In the uni-app framework, pages are first created based on the configuration in pages.json. The DOM is created based on the template components in the page. After that, onload is triggered.
Tabbar Settings#
The list in tabBar is an array that can only configure a minimum of 2 and a maximum of 5 tabs, sorted in the order of the array. The tabBar settings are located in the page.js
file. Tabbar pages must be included in the pages array in the document.
Deleting the Top Navigation Bar#
uni-app Development - Top Navigation Bar - Juejin (juejin.cn)
Property | Type | Default Value | Description |
---|---|---|---|
navigationStyle | String | default | Navigation bar style, only supports default/custom. Custom means canceling the default native navigation bar; see Usage Notes |
pages.json Page Routing | uni-app Official Website (dcloud.net.cn)
By setting the following parameters in manifest.json
, you can avoid issues with the app being obscured by the phone's top status bar or water drop screen. You can also add a visual block at the top to fill the top status bar area to solve this issue.
"app-plus" : {
"statusbar": {
"immersed": false
}
}
Differences Between uni.setStorageSync
and Vuex Store Storage#
uni.setStorageSync
is a local storage API provided by uni-app for storing data on the client side. It is similar to the localStorage
and sessionStorage
in the Web Storage API. Vuex is the official state management pattern for Vue.js
, used to centrally manage the state of all components in the application. Local storage is a way to store data on the client side, while state management is a pattern for centrally managing the state of an application.
- Storage Location:
uni.setStorageSync
stores data in the client's local storage; Vuex store stores data in memory. - Persistence: Data in
uni.setStorageSync
is persistent; data in the Vuex store will be lost after the page refreshes. - Reactivity: Data in the Vuex store is reactive; data in
uni.setStorageSync
is not reactive. - State Management: The Vuex store provides complex state management functions;
uni.setStorageSync
is mainly used for simple data storage. - Security: Data in
uni.setStorageSync
is more vulnerable to attacks; data in the Vuex store is better protected because it is in memory rather than client-side local storage.
uni.setStorage(OBJECT) @setstorage | uni-app Official Website (dcloud.net.cn)
Using Global Data Management in uni-app#
Client-side Storage - Learning Web Development | MDN (mozilla.org)
Initialize in main.js
or App.vue
:
Using Global Variables or Store#
In the JS files under the store folder, you can see the stored global variables.
Caching#
Cache data for use on other pages.
uni.setStorage({key, data, success, fail, complete})
: Asynchronously stores data in local storage, providing callback functions for success, failure, and completion.uni.getStorage({key, success, fail, complete})
: Asynchronously retrieves data from local storage, providing callback functions for success, failure, and completion.uni.setStorageSync(key, data)
: Synchronously stores data in local storage, executing immediately without callback functions.uni.getStorageSync(key)
: Synchronously retrieves data from local storage, executing immediately without callback functions.
// Asynchronous method
uni.setStorage({
key: 'key',
data: 'value',
success: function () {
console.log('Data stored successfully');
},
fail: function (error) {
console.log('Data storage failed:', error);
}
});
// Retrieve data
uni.getStorage({
key: 'key',
success: function (res) {
console.log('Data retrieved successfully:', res.data);
},
fail: function (error) {
console.log('Data retrieval failed:', error);
}
});
// Synchronous method
uni.setStorageSync('projectId', this.projectId); // Cache data
let x = uni.getStorageSync('projectId'); // Retrieve data
Usage of Dropdown Selection Component#
Choose to use the uniapp community's select-lay - DCloud Plugin Market plugin. This plugin can achieve custom data index objects, which work well for displaying single selections of complex data structures.
<select-lay :value="tval" name="name" :options="datalist" @selectitem="selectitem"></select-lay>
The custom data structure is written as follows:
<select-lay :zindex="998" :value="choicedID" name='Name' placeholder="Please select topology name"
slabel="t_name" svalue="t_id"
:options="project" @selectitem="choicet_Name"></select-lay>
The value must match the variable value that the selection box ultimately passes; otherwise, the result of the selection will not be displayed in the UI after selection.
Component Layer Settings#
In the UI, different components can be displayed on top of others by setting different layers through parameters.
In uniapp, some components can set the component's layer using the z-index
parameter. The z-index property sets the z-axis order of elements during rendering. In the same stacking context, elements with a higher z-index will cover those with a lower z-index. In simple terms, the higher the value set for this parameter, the higher it will be displayed.
The default value of z-index on the app side is 0, while on the web side, it is auto.
z-index | uni-app-x (dcloud.net.cn)
Usage of Props Parameters#
props
can be an array or an object used to receive data from parent components. props
can be simple arrays or use objects as alternatives, allowing for advanced options such as type checking, custom validation, and setting default values.
Form Checking and Validation#
.some Method
The .some()
method is a JavaScript array method used to test whether at least one element in the array satisfies the provided testing function. If at least one element causes the testing function to return true
, then the .some()
method will return true
; otherwise, it returns false
.
// Is there any number greater than 10?
const numbers = [1, 5, 10, 15, 20];
const hasNumberGreaterThanTen = numbers.some(number => number > 10);
console.log(hasNumberGreaterThanTen); // Output: true
Check if corresponding two sets of variables are the same.
// Check which properties have changed
const changedProperties = ['email', 'nickname', 'phone'].some(prop => {
return this.accountForm[prop] !== this.profile[prop];
});
Implementation of Popup#
Implemented through the uview's u-popup component.
<u-popup :show="popShow" mode="center">
<view >
<text>Confirm cancel?</text>
<u-button type="primary" style="margin-top: 5rpx;" text="Return" @click="popShow = false"></u-button>
<u-button type="error" style="margin-top: 5rpx;" text="Confirm" @click="cancelAppoint(cancelId)"></u-button>
</view>
</u-popup>
Delayed Redirection After Popup Message#
uni.showToast({
title: 'Appointment successful!',
duration: 1000
});
setTimeout(function() {
uni.reLaunch({
url: '/pages/tabBar/home/index'
});
}, 1000);
Sending Query Data via POST#
Problem#
Sending requests with query data using POST.
Background#
When using uview to send requests, it can be configured in advance. Below is the configuration provided by the uview official website. By defining and exporting the configuration, global settings for all requests can be achieved. If the datatype in headers is not configured, uview defaults to sending a body request with POST. If you want to send data using a POST request, you need to modify the value of Content-Type in headers.
const install = (Vue, vm) => {
baseURL: '',
header: {},
method: 'GET',
dataType: 'json',
// #ifndef MP-ALIPAY
responseType: 'text',
// #endif
// Note: If a local custom property has the same name as a global custom property, the latter will override the former, equivalent to Object.assign(global, local)
custom: {}, // Global custom parameter default values
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
timeout: 60000,
// #endif
// #ifdef APP-PLUS
sslVerify: true,
// #endif
// #ifdef H5
// Whether to carry credentials (cookies) during cross-domain requests, only supported in H5 (HBuilderX 2.6.15+)
withCredentials: false,
// #endif
// #ifdef APP-PLUS
firstIpv4: false, // Prioritize using ipv4 during DNS resolution, only supported in App-Android (HBuilderX 2.8.0+)
// #endif
// Local takes precedence over global, returns the current request's task, options. Do not modify options here. Not required
// getTask: (task, options) => {
// Equivalent to setting the request timeout to 500ms
// setTimeout(() => {
// task.abort()
// }, 500)
// },
// Global custom validator. The parameter is statusCode and must exist; no need to check for empty cases.
validateStatus: (statusCode) => { // statusCode must exist. This example is for global default configuration
return statusCode >= 200 && statusCode < 300
}
}
Solution#
When sending a query request with POST, the value of Content-Type in headers should be application/x-www-form-urlencoded
, while for sending a body request, it should be application/json
. Since the above is a global setting and the project uses POST to send query data less frequently, you can set the value of Content-Type in headers separately when sending query requests.
// Sending query parameters via HTTP POST
export function http_a_post_query(path, params){
let formBody = Object.keys(params).map(key => key + '=' + params[key]).join('&');
console.log('http_a_post=', projectConfig.baseUrl_a + path);
return http.post(projectConfig.baseUrl + path, params, {header: {'content-type': 'application/x-www-form-urlencoded'}});
}
Image Upload#
- Use
uni.chooseImage
to select an image from files and useuni.uploadFile
to upload the image. After selecting the image, get the file path and upload it to the server using the POST protocol withcontent-type=multipart/form-data
. At the same time, receive the image address returned by the server.
uploadPic() {
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
success: res => {
console.log(projectConfig.baseUrl + '/v1/dms/upload/picture/local');
uni.uploadFile({
url: projectConfig.baseUrl + '/v1/dms/upload/picture/local',
filePath: res.tempFilePaths[0],
name: 'files',
header: {
'Authorization': 'Bearer ' + uni.getStorageSync('token'),
},
complete: (res) => {
console.log('res:', JSON.parse(res.data)[0]);
this.form.device_image = JSON.parse(res.data)[0];
this.$u.toast('Image upload completed!');
this.upPicMsg = 'Re-upload'
}
})
}
})
},
Implementation of Statistical Charts#
Guide - uCharts Cross-Platform Chart Library
Idea: Format the data returned from the backend into a format accepted by the component and implement it through the chart component.
HTML Part#
<qiun-data-charts :ontouch="true" type="line" :opts="line_opts2" :localdata="trendData" />
:ontouch="true"
indicates whether the component should respond to touch events.type="line"
specifies that the chart type is a line chart.:opts="line_opts2"
is an object containing the chart configuration, set in local JS, such as axis labels, grid lines, etc.:localdata="trendData"
is an object containing the dataset to be displayed.
Data Format#
First Format
let res = {
categories: ["2016","2017","2018","2019","2020","2021"], // Labels for the horizontal axis
series: [
{
name: "Target Value",
data: [35,36,31,33,13,34] // First data series
},
{
name: "Completion Amount",
data: [18,27,21,24,6,28] // Second data series
}
]
};
Second Format
localdata:[
{value:35, text:"2016", group:"Target Value"},
{value:18, text:"2016", group:"Completion Amount"},
{value:36, text:"2017", group:"Target Value"},
{value:27, text:"2017", group:"Completion Amount"},
{value:31, text:"2018", group:"Target Value"},
{value:21, text:"2018", group:"Completion Amount"},
{value:33, text:"2019", group:"Target Value"},
{value:24, text:"2019", group:"Completion Amount"},
{value:13, text:"2020", group:"Target Value"}, // Determine two or more categories of data based on group
{value:6, text:"2020", group:"Completion Amount"},
{value:34, text:"2021", group:"Target Value"},
{value:28, text:"2021", group:"Completion Amount"}
]
Implementation of Tables#
Problem#
The built-in table in uniapp cannot complete operations like merging cells, and directly using rowspan
and colspan
may cause compatibility issues across different platforms.
uniapp uni-table table component merging cells_uni-table merging cells-CSDN Blog
Method#
Directly use the table
, tr
, and td
tags in HTML. It is important to note that v-for cannot be used in the following tags:
thead
tbody
tfoot
th
td
In practical use, if you want to use a loop to display data of different lengths returned from the backend, you can nest another layer outside.
<template v-for="(type, typeIndex) in deviceParam">
<tr :key="typeIndex">
<!-- Type title row, using rowspan attribute to merge cells -->
<th :rowspan="type.deviceParamInfoVos.length + 1">
{{ type.device_param_type_name }}
</th>
<!-- Use v-for to iterate over each parameter -->
<tr v-for="param in type.deviceParamInfoVos" :key="param.device_param">
<td>{{ param.device_param_name }}</td>
<td>{{ param.device_param_value + param.device_param_unit }}</td>
</tr>
</tr>
</template>