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 is needed than what HTML syntax allows, 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 the content, such as defining paragraphs, headings, and data tables, or embedding images and videos in a 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 used to create dynamically updating content, control multimedia, animate images, 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 in 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 expected value of a directive attribute is 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 calls 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 can indicate the current state of an 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 hooks that are asynchronous, such as created and mounted. These hooks allow you to perform asynchronous operations after the component has been 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 homepage
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 the 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 pauses 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 complete or fail in the future, 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 pauses 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 with a try...catch
statement.
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 in 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 Components technology suite; it is a placeholder inside a web component that you can fill with your own markup, thereby creating a separate DOM tree that can be rendered 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 prefixed with $ are often provided by the Vue framework itself for performing Vue-related operations or accessing the internal state of the Vue instance.
Usage of : in template#
The v-bind
attribute is referred to as 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 will 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, such as v-model
, v-if
, v-for
, etc., they are not used to bind HTML attributes but are Vue-specific template directives for implementing 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 using :
as shorthand for v-bind
. For example, :id="dynamicId"
in <div :id="dynamicId">
indicates 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 cache and store it in the Vuex state manager for easy access when needed.
getToken () {
// Get token from local cache
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, with the value being the corresponding child component instance or DOM element.
Note: The value of $refs
is undefined
before the component rendering is complete. 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, usually 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:
- 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 constant)|function|class|file|module name
syntax. There can be multiple exports, but only 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 creating a plugin that can be used in Vue applications.
The install
function typically receives 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.
Inside 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 for implementing inheritance and sharing 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.
The 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 use 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 within it. Afterward, these methods can be accessed 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 the parent component. Props can be declared and registered on child components, with the parent component defining the values for the declared parameters. Updates to parent props flow down to child components but cannot flow back. 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 uses a centralized store 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 unified methods | 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 multiple modules and complex 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#
Every 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 will also run.
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 cache token
if (this.token != '' && this.token != null) {
// Redirect to the homepage
uni.switchTab({
url: '/pages/tabBar/home/index'
});
} else {
this.getCode();
this.getAccount();
}
},
onShow, onHide, onUnload#
Note that page display is an event that can be triggered repeatedly.
When page a first enters, it triggers onShow for page a.
When a jumps to page b, a will trigger onHide, while b will trigger onShow.
However, when b is closed, b will trigger onUnload, and when a appears again, it will trigger onShow again.
In tab bar 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 of the page to complete 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 problem.
"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 for centrally managing 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 application's state.
- Storage Location:
uni.setStorageSync
stores data in local client storage; Vuex store stores data in memory. - Persistence: Data in
uni.setStorageSync
is persistent; data in Vuex store will be lost after the page refresh. - Reactivity: Data in Vuex store is reactive; data in
uni.setStorageSync
is not reactive. - State Management: Vuex store provides complex state management functions;
uni.setStorageSync
is mainly for simple data storage. - Security: Data in
uni.setStorageSync
is more vulnerable to attacks; data in Vuex store is more protected because it is in memory rather than client 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 in other pages.
uni.setStorage({key, data, success, fail, complete})
: Asynchronously stores data in local cache, providing callbacks for success, failure, and completion.uni.getStorage({key, success, fail, complete})
: Asynchronously retrieves data from local cache, providing callbacks for success, failure, and completion.uni.setStorageSync(key, data)
: Synchronously stores data in local cache, executing immediately without callbacks.uni.getStorageSync(key)
: Synchronously retrieves data from local cache, executing immediately without callbacks.
// 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
Using the 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 a 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 selection result will not display in the UI after selection.
Component Layer Settings#
During the display process of different components in the UI, different layers can be set through parameters to make some components display above others.
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 the display layer.
The default z-index value for the app is 0, while for the web 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 the parent component. 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 returns true
from the testing function, 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 the corresponding two groups of variables are the same.
// Check which properties have changed
const changedProperties = ['email', 'nickname', 'phone'].some(prop => {
return this.accountForm[prop] !== this.profile[prop];
});
Implementing Pop-ups#
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 with 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. Without configuring the datatype in headers, uview defaults to sending POST requests as body requests. If you want to send data with a POST request, you need to change 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, returning the current request's task, options. Do not modify options here. Not required
// getTask: (task, options) => {
// Equivalent to setting a request timeout of 500ms
// setTimeout(() => {
// task.abort()
// }, 500)
// },
// Global custom validator. The parameter is statusCode and must exist; no need to check for null 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 a query request.
// 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 the file 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'
}
})
}
})
},
Implementing 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 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"}
]
Implementing Tables#
Problem#
The built-in table in uniapp cannot perform 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 HTML tags table
, tr
, and td
to implement it. Note that v-for
cannot be used within the following tags:
thead
tbody
tfoot
th
td
In practical use, if you want to use a loop to display varying lengths of data 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>