Vue monitors object attributes to achieve linkage effect

Posted by danieloberg on Thu, 24 Feb 2022 08:04:40 +0100

Business background

There is such a requirement in the project. A form stores supplier information. At the same time, it is necessary to select different suppliers to bring out the basic information and company qualification documents of the corresponding suppliers. Similar to a cascade operation, the supplier information is dynamically displayed through the selected supplier Id.

 

Train of thought analysis

To achieve the effect of dynamic display, we need to request the back-end interface to get the data returned to the front-end and render it to the form of the page. Here, the front and back-end data interaction will not be introduced in detail, so let's enter the implementation mode.

Implementation mode

Because selecting a supplier is a drop-down box component in the form, the first response is the Chang event using the drop-down payment. When the drop-down box changes, request the back end. The value of the drop-down box is usually stored in the form of key value pairs, that is, [key:"",value: ""]. Here, key is the supplier's Id and value is the supplier's name. We only need to take the supplier Id to request the back-end interface to find out the supplier information at this time, and then render it to the form. But the problem comes. In general, the Chang event of drop-down payment can solve this business requirement. However, due to the encapsulation of the company's project, the drop-down box component is uniformly encapsulated and made into a component. If we change the component directly, it will affect the use of other pages. So at this time, we consider using Vue's watch, that is, listening to events. When the supervisor hears that the attribute of supplier Id has changed, our business processing is carried out.

Vue listening: Vue JS provides a method watch, which is used to observe data changes on Vue instances. Corresponding to an object, the key is the observation expression, and the value is the corresponding callback. The value can also be a method name or an object containing options. It is divided into deep listening and shallow listening. Deep listening can listen to each attribute under the object level by level. When each attribute changes, the callback function will be triggered.  

There is also an attribute "deep" in watch. The default value is "false", which indicates whether to listen deeply. The id of the supplier we need to listen to here is an attribute (manuSupplier) in the updateRequest object, but in fact, this attribute is also an object type. If you use deep listening, the callback function will be triggered all the time, which consumes a lot of memory and is not good for the user experience. So we monitor manusupplier directly id attribute.

immediate:true. The representative declared updaterequest in wacth manuSupplier. The handler method is executed immediately after the id method. Here, we don't need to execute the handler method immediately. We only need to execute the callback function when the value really changes, that is, when different supplier IDs are selected. Therefore, if we don't set it, the default is false. The code is attached below

 data() {
      return {
        data() {
          return {
            // Modify object
            updateRequest: {
              hospEqpId: '',
              factSerialNo: '',
              deptId: '',
              hospCode: undefined,
              eqpProdId: '',
              contrId: '',
              eqpTagValueList: [],
              dealerSupplierId: '',
              manuSupplierId: '',
              'manuSupplier': {
                'id': '',
                'type': '',
                'supName': '',
                'phone': '',
                'contactName': '',
                'contactPhone': '',
                'license': '',
                'hospCode': '',
                'createDateTime': [],
                'companyCertification': '',
                'certificationInfoList': [],
                'invalidFile': []
              },
              'dealerSupplier': {
                'id': '',
                'type': '',
                'supName': '',
                'phone': '',
                'contactName': '',
                'contactPhone': '',
                'license': '',
                'hospCode': '',
                'createDateTime': [],
                'companyCertification': '',
                'certificationInfoList': [],
                'invalidFile': []
              }
            },
            // Query supplier request object
            querySupplierRequest: {
              hospCode: '',
              id: ''
            }
          }
        }
      }
    }
 watch: {
      // Listen for changes in the attribute value of the manufacturer supplier drop-down box
      'updateRequest.manuSupplier': {
        handler(newVal, oldVal) {
          if (newVal) {
            this.querySupplierRequest.hospCode = this.hospCode
            this.querySupplierRequest.id = newVal
            queryBySupplierIdRequest(this.querySupplierRequest).then(res => {
              this.updateRequest.manuSupplier = res
            })
          }
        }
      },
      // Listen for the change of attribute value of distribution supplier drop-down box
      'updateRequest.dealerSupplier.id': {
        handler(newVal, oldVal) {
          if (newVal) {
            this.querySupplierRequest.hospCode = this.hospCode
            this.querySupplierRequest.id = newVal
            queryBySupplierIdRequest(querySupplierRequest).then(res => {
              this.updateRequest.dealerSupplier = res
            })
          }
        }
      }
    }

When I wrote this step, I thought I had solved the problem, but I found a problem when I returned to the page to view the form. The information of the manufacturer and supplier is wrong after the two supervision} listening and execution. The information of manufacturers and suppliers is overwritten with the information of distribution suppliers.

After the debug mode, it is found that after listening to the change of the assigned value of the distribution supplier, because the back-end interface that triggers the callback function request after two listening is the same, and the request parameter querySupplierRequest is a constant defined in the data source. Because the request is an asynchronous request encapsulated by ajax, after you listen to the change of the dealer supplier id, you assign a reverse value to the id of the request parameter object queryRequest, which becomes the dealer id. Therefore, at this time, the manufacturer's supplier id is actually assigned to the dealer's id. At this time, you go to the back end to ask for the information of the dealer. Therefore, when requesting the back-end interface, you cannot change the same constant object into a local object. The corrected code is attached below

 watch: {
    // Listen for changes in the attribute value of the manufacturer supplier drop-down box
    'updateRequest.manuSupplier.id': {
      handler(newVal,oldVal) {
        if (newVal) {
          let obj={
            id : '',
            hospCode : ''
          }
          obj.hospCode=this.hospCode
          obj.id=newVal
          queryBySupplierIdRequest(obj).then(res => {
            this.updateRequest.manuSupplier = res
          })
        }
      }
    },
    // Listen for the change of attribute value of distribution supplier drop-down box
    'updateRequest.dealerSupplier.id': {
      handler(newVal,oldVal) {
        if (newVal) {
          let obj={
            id : '',
            hospCode : ''
          }
          obj.hospCode=this.hospCode
          obj.id=newVal
          queryBySupplierIdRequest(obj).then(res => {
            this.updateRequest.dealerSupplier = res
          })
        }
      }
    }
  }

It can be seen that the information of the manufacturer and supplier is correct at this time, and every time you switch suppliers, you will listen to and execute your business code and reassign it to the form, realizing the effect of linkage.

Topics: Java Spring Vue Vue.js