vue2+konva9.2.0的结合使用

在线文档

  • 使用
<div id="flow-container"></div>

<div
  v-show="popoverStatus"
  class="popover-container"
  :style="{ top: popoverTop + 'px', left: popoverLeft + 'px' }"
>
  <div class="items" v-if="!popoverShowInverter">
    <div class="item">
      <div class="item-label">编号</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.channelNum) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">SN号</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.optimizerSncode) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">型号</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.optimizerModel) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">优化器名称</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.optimizerName) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">通道编号</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.channelNo) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">发电量 (kWh)</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.cap) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">输出电压 (V)</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.outv) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">输出电流 (A)</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.outa) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">输出功率 (W)</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.outPower) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">输入电压 (V)</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.inv) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">输入电流 (A)</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.ina) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">通道状态</div>
      <div class="item-value">
        {{ $t(`DEV.COM_STATE.${popoverData.status}`) }}
      </div>
    </div>
  </div>
  <div class="items" v-else>
    <div class="item">
      <div class="item-label">编号</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.inventerNum) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">SN号</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.inventerSnCode) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">型号</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.inventerModel) }}
      </div>
    </div>
    <div class="item">
      <div class="item-label">逆变器名称</div>
      <div class="item-value">
        {{ $utils.handlerItemData(popoverData.name) }}
      </div>
    </div>
  </div>
</div>

<style lang='scss'>
#flow-container {
  width: 100%;
  height: 100%;
}
.popover-container {
  position: fixed;
  left: 10px;
  top: 20px;
  display: inline-block;
  z-index: 101;
  background: rgba(255, 255, 255, 0.8);
  .items {
    padding: 16px;
    .item {
      display: flex;
      align-items: center;
      + .item {
        margin-top: 10px;
      }
      &-label {
        min-width: 74px;
        height: 16px;
        line-height: 16px;
        font-size: 12px;
        color: #757575;
      }
      &-value {
        min-width: 74px;
        height: 16px;
        line-height: 16px;
        margin-left: 12px;
        font-size: 12px;
        color: #757575;
      }
    }
  }
}
</style>
import Konva from 'konva'
import head_img from '../dataScreen/img/view-head.png'
import online_img from '../dataScreen/img/view-online.png'
import offline_img from '../dataScreen/img/view-offline.png'
export default {
  name: 'StationView',
  components: {},
  data() {
    return {
      layer: null,
      stage: null,
      defaultConfig: {
        rectWith: 74, // 矩形的宽
        rectHeight: 100, // 矩形的高
        lineStrokeWidth: 1,
        grey: 'rgb(155,162,160)',
        lineColor: '#D9D9D9', // 线的颜色
        scaleX: 1,
        scaleY: 1
      },
      // 开始绘制的坐标点
      startX: 10,
      startY: 10,
      initStartX: 10,
      initStartY: 10,
      // 长线 短线的长度
      longLine: 62,
      shortLine: 24,
      // 多少块换行
      wrapBlock: 10,
      // 上下盒子的间隔
      boxSpace: 40,
      // 大行之间的距离
      bigBlockSpace: 66,
      // 坐标点的位置
      pointsArr: [],
      groupArr: [],
      onlineImg: null,
      offlineImg: null,
      headImg: null,
      formData: [
        {
          inventerId: 11111,
          inventerNum: '1',
          inventerSnCode: '111111',
          cap: 1234,
          name: '逆变器名称',
          optimizerRealList: [
            {
              inventerId: 11111,
              inventerNum: '1',
              inventerSnCode: '111111',
              optimizerNum: '1',
              optimizerSncode: '111111',
              cap: 1111,
              channelNo: 1111,
              name: '通道1名称',
              channelNum: '1.1.1',
              timestamp: 1111
            },
            {
              inventerId: 11111,
              inventerNum: '1',
              inventerSnCode: '111111',
              optimizerNum: '1',
              optimizerSncode: '111111',
              cap: 1122,
              channelNo: 1122,
              name: '通道2名称',
              channelNum: '1.1.2',
              timestamp: 1122
            },
            {
              inventerId: 11111,
              inventerNum: '1',
              inventerSnCode: '111111',
              optimizerNum: '1',
              optimizerSncode: '111111',
              cap: 1133,
              channelNo: 1133,
              name: '通道3名称',
              channelNum: '1.1.3',
              timestamp: 1133
            },
            {
              inventerId: 11111,
              inventerNum: '1',
              inventerSnCode: '111111',
              optimizerNum: '2',
              optimizerSncode: '223333',
              cap: 2222,
              channelNo: 2222,
              name: '通道21名称',
              channelNum: '1.2.1',
              timestamp: 2222
            },
            {
              inventerId: 11111,
              inventerNum: '1',
              inventerSnCode: '111111',
              optimizerNum: '2',
              optimizerSncode: '223333',
              cap: 2222,
              channelNo: 2222,
              name: '通道22名称',
              channelNum: '1.2.2',
              timestamp: 2222
            },
            {
              inventerId: 11111,
              inventerNum: '1',
              inventerSnCode: '111111',
              optimizerNum: '2',
              optimizerSncode: '223333',
              cap: 2222,
              channelNo: 111,
              name: '通道22名称',
              channelNum: '1.2.3',
              timestamp: 2345
            }
          ]
        },
        {
          inventerId: 34344,
          inventerNum: '2',
          inventerSnCode: '',
          cap: 5678,
          name: '逆变器2名称',
          optimizerRealList: [
            {
              inventerId: 34344,
              inventerNum: '2',
              inventerSnCode: '',
              optimizerNum: '1',
              optimizerSncode: '5554545',
              cap: 343334,
              channelNo: 43434,
              name: '通道22名称',
              channelNum: '2.1.1',
              timestamp: 34343434
            },
            {
              inventerId: 34344,
              inventerNum: '2',
              inventerSnCode: '',
              optimizerNum: '1',
              optimizerSncode: '5554545',
              cap: 343344,
              channelNo: 34343,
              name: '通道22名称',
              channelNum: '2.1.2',
              timestamp: 45455
            },
            {
              inventerId: 34344,
              inventerNum: '2',
              inventerSnCode: '',
              optimizerNum: '1',
              optimizerSncode: '5554545',
              cap: 545454,
              channelNo: 454545,
              name: '通道22名称',
              channelNum: '2.1.3',
              timestamp: 45454545
            },
            {
              inventerId: 34344,
              inventerNum: '2',
              inventerSnCode: '',
              optimizerNum: '2',
              optimizerSncode: '',
              cap: 4545,
              channelNo: 0,
              name: '通道22名称',
              channelNum: '2.2.1',
              timestamp: 0
            },
            {
              inventerId: 34344,
              inventerNum: '2',
              inventerSnCode: '',
              optimizerNum: '2',
              optimizerSncode: '',
              cap: 0,
              channelNo: 0,
              name: '通道22名称',
              channelNum: '2.2.2',
              timestamp: 0
            },
            {
              inventerId: 34344,
              inventerNum: '2',
              inventerSnCode: '',
              optimizerNum: '2',
              optimizerSncode: '',
              cap: 0,
              channelNo: 0,
              name: '通道22名称',
              channelNum: '2.2.3',
              timestamp: 0
            }
          ]
        }
      ],
      popoverShowInverter: false,
      popoverStatus: false,
      popoverData: {},
      popoverTop: 0,
      popoverLeft: 0
    }
  },
  computed: {
    // 获取图层动态的高度
    flowHeight() {
      let height = 0
      this.formData.forEach((item, index) => {
        height +=
          this.defaultConfig.rectHeight + (index > 0 ? this.bigBlockSpace : 0)
        if (item.optimizerRealList && item.optimizerRealList.length) {
          height +=
            Math.floor(item.optimizerRealList.length / this.wrapBlock) *
            (this.boxSpace + this.defaultConfig.rectHeight)
        }
      })
      return height
    },
    // 获取图层动态的宽度
    flowWidth() {
      // 求最多的列数
      let num = 0
      this.formData.forEach((item, index) => {
        if (
          item.optimizerRealList &&
          item.optimizerRealList.length &&
          item.optimizerRealList.length > num
        ) {
          num = item.optimizerRealList.length
        }
      })
      num = num > this.wrapBlock ? this.wrapBlock : num
      return (
        this.defaultConfig.rectWith +
        this.longLine +
        this.defaultConfig.rectWith * num +
        this.shortLine * (num - 1)
      )
    }
  },
  watch: {
    formData: {
      handler(nv, ov) {
        if (nv) {
          this.$nextTick((_) => {
            this.initGraph()
            this.initPoints()
            this.render()
            this.eventListen()
          })
        }
      },
      immediate: true
    }
  },
  async mounted() {
    this.initImage()
    // 屏幕尺寸大小变化
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy() {
    console.log('页面销毁,取消监听resize')
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    initGraph() {
      this.stage && this.stage.clearCache() // 多次绘制清除缓存
      // 恢复默认比例
      this.defaultConfig.scaleX = 1
      this.defaultConfig.scaleY = 1
      const el = document.querySelector('#flow-container')
      if (!el) return
      // console.log(el.offsetWidth, el.offsetHeight, this.flowHeight)
      // 重新绘制起始点坐标,使图层水平垂直居中,最小的x y起始点
      this.startX =
        (el.offsetWidth - this.flowWidth) / 2 > this.initStartX
          ? (el.offsetWidth - this.flowWidth) / 2
          : this.initStartX
      this.startY =
        (el.offsetHeight - this.flowHeight) / 2 > this.initStartY
          ? (el.offsetHeight - this.flowHeight) / 2
          : this.initStartY
      this.initStartX = this.startX
      this.initStartY = this.startX
      this.stage = new Konva.Stage({
        container: el,
        width: el.offsetWidth,
        height: el.offsetHeight,
        draggable: true
      })
      this.layer = new Konva.Layer()
      this.stage.add(this.layer)
      this.layer.draw()
    },
    initPoints() {
      // 坐标点的位置
      this.pointsArr = []
      for (let i = 0, len = this.formData.length; i < len; i++) {
        // 获取前面列的高度
        if (i > 0) {
          const item = this.formData[i - 1]
          this.startY += this.defaultConfig.rectHeight + this.bigBlockSpace
          if (item.optimizerRealList && item.optimizerRealList.length) {
            this.startY +=
              Math.floor(item.optimizerRealList.length / this.wrapBlock) *
              (this.boxSpace + this.defaultConfig.rectHeight)
          }
        }
        this.getPoints(this.formData[i], i)
      }
    },
    async initImage() {
      if (!this.onlineImg) {
        this.onlineImg = await this.loadImage(online_img)
      }
      if (!this.offlineImg) {
        this.offlineImg = await this.loadImage(offline_img)
      }
      if (!this.headImg) {
        this.headImg = await this.loadImage(head_img, '1')
      }
    },
    loadImage(imgUrl, type) {
      return new Promise((resolve) => {
        Konva.Image.fromURL(imgUrl, (darthNode) => {
          const rHeight = type
            ? this.defaultConfig.rectHeight
            : this.defaultConfig.rectHeight - 3
          darthNode.setSize({
            width: this.defaultConfig.rectWith,
            height: rHeight
          })
          resolve(darthNode.clone())
        })
      })
    },
    /**
     * @description 获取坐标点的位置
     */
    getPoints(content = {}, index) {
      let startX = this.startX
      // 表头
      this.pointsArr.push({
        type: 'Inverter',
        points: [startX, this.startY],
        name: content.inventerName,
        label: content.label,
        value: content.cap,
        version: content.inventerNum,
        id: index + '',
        status: content.status
      })
      const x1 = startX + this.defaultConfig.rectWith
      const y1 = this.startY + this.defaultConfig.rectHeight / 2
      const x2 = x1 + this.longLine
      // 长连线
      this.pointsArr.push({
        type: 'Line',
        points: [x1, y1, x2, y1]
      })
      startX = x2 // 重置起始坐标点
      let oldInt = 0 // 记录上一次的第几行
      for (let i = 0, len = content.optimizerRealList.length; i < len; i++) {
        const item = content.optimizerRealList[i]
        const int = Math.floor(i / this.wrapBlock) // 第几行
        const mod = i % this.wrapBlock // 第几列
        if (oldInt !== int) {
          // 转接线
          this.pointsArr.push({
            type: 'Line',
            points: [
              x1 + this.longLine / 2,
              y1,
              x1 + this.longLine / 2,
              y1 + (this.defaultConfig.rectHeight + this.boxSpace) * int,
              x1 + this.longLine,
              y1 + (this.defaultConfig.rectHeight + this.boxSpace) * int
            ]
          })
        }
        oldInt = int
        // 起始坐标+(盒子宽度+盒子之间的连线长度)*mod
        const x = startX + (this.defaultConfig.rectWith + this.shortLine) * mod
        // 起始坐标+(盒子宽度+盒子上下的距离)*int
        const y =
          this.startY + (this.defaultConfig.rectHeight + this.boxSpace) * int
        this.pointsArr.push({
          type: 'Optimizer',
          points: [x, y],
          name: item.optimizerName,
          label: item.label,
          value: item.cap,
          version: item.channelNum,
          status: item.status,
          id: index + ':' + i
        })
        // 最后一列不连线、最后一个也不连线
        if (
          mod !== this.wrapBlock - 1 &&
          int * this.wrapBlock + mod + 1 !== len
        ) {
          this.pointsArr.push({
            type: 'Line',
            points: [
              x + this.defaultConfig.rectWith,
              y + this.defaultConfig.rectHeight / 2,
              x + this.defaultConfig.rectWith + this.shortLine,
              y + this.defaultConfig.rectHeight / 2
            ]
          })
        }
      }
    },
    createInverter(data = {}) {
      const group = new Konva.Group({
        x: data.points[0],
        y: data.points[1],
        id: data.id
      })
      const textConfig = {
        width: this.defaultConfig.rectWith, // 盒子的宽度
        height: 17,
        lineHeight: 17,
        align: 'center',
        verticalAlign: 'middle',
        fontSize: 12
      }
      this.layer.add(group)
      this.groupArr.push(group)

      const darthNode = this.headImg.clone()
      group.add(darthNode)
      const rectText = new Konva.Text({
        y: 9,
        ...textConfig,
        text: '= / ~',
        fill: '#fff'
      })
      group.add(rectText)
      const rectText2 = new Konva.Text({
        y: 38,
        ...textConfig,
        text: data.value,
        fill: '#000'
      })
      group.add(rectText2)
      const rectText3 = new Konva.Text({
        y: 55,
        ...textConfig,
        text: 'kWh',
        fill: '#79889C'
      })
      group.add(rectText3)
      const rectText4 = new Konva.Text({
        y: 79,
        ...textConfig,
        text: data.version,
        fill: '#79889C'
      })
      group.add(rectText4)
    },
    createOptimizer(data = {}, lienStatus = true) {
      const group = new Konva.Group({
        x: data.points[0],
        y: data.points[1] + 3, // 3为(100-94)/2,盒子的外边距
        id: data.id
      })
      const textConfig = {
        width: this.defaultConfig.rectWith, // 盒子的宽度
        height: 17,
        lineHeight: 17,
        align: 'center',
        verticalAlign: 'middle',
        fontSize: 12
      }
      this.layer.add(group)
      this.groupArr.push(group)
      // 在线 离线
      if (lienStatus) {
        const darthNode = this.onlineImg.clone()
        group.add(darthNode)
        // 文字显示
        const valueText = new Konva.Text({
          y: 25,
          ...textConfig,
          fontSize: 14,
          text: data.value,
          fill: '#fff'
        })
        group.add(valueText)
        const unitText = new Konva.Text({
          y: 46,
          ...textConfig,
          text: 'kWh',
          fill: '#79889C'
        })
        group.add(unitText)
        const versionText = new Konva.Text({
          y: 77,
          ...textConfig,
          text: data.version,
          fill: '#79889C'
        })
        group.add(versionText)
      } else {
        const darthNode = this.offlineImg.clone()
        group.add(darthNode)
        // 文字显示
        const valueText = new Konva.Text({
          y: 27,
          ...textConfig,
          fontSize: 14,
          text: '--',
          fill: '#fff'
        })
        group.add(valueText)
        const versionText = new Konva.Text({
          y: 77,
          ...textConfig,
          text: data.version,
          fill: '#fff'
        })
        group.add(versionText)
      }
    },
    render() {
      this.pointsArr.forEach((item, index) => {
        // console.log(item)
        if (item.type === 'Inverter') {
          this.createInverter(item)
        } else if (item.type === 'Optimizer') {
          this.createOptimizer(item, item.status)
        } else if (item.type === 'Line') {
          const line = new Konva.Line({
            points: item.points,
            stroke: this.defaultConfig.lineColor,
            strokeWidth: this.defaultConfig.lineStrokeWidth
          })
          this.layer.add(line)
        }
      })
    },
    eventListen() {
      if (!this.stage) return
      // 放大缩小
      this.stage.on('wheel', (e) => {
        this.popoverStatus = false
        this.popoverData = {}
        this.handleZoom(e.evt, e.evt.wheelDelta)
      })
      const setCursor = (e, val = 'pointer') => {
        const stage = e.target.getStage()
        if (stage) {
          stage.container().style.cursor = val
        }
      }
      this.groupArr.forEach((group) => {
        group.on('click', (e) => {
          // console.log('点击事件', group.id())
          e.cancelBubble = true // 阻止事件冒泡
          setCursor(e)
          this.popoverStatus = true
          const idArr = group.id().split(':')
          this.popoverData =
            idArr.length > 1
              ? this.formData[idArr[0]].optimizerRealList[idArr[1]]
              : this.formData[idArr[0]]
          console.log(this.popoverData)
          // 有optimizerRealList说明是逆变器
          if (this.popoverData.optimizerRealList) {
            this.popoverShowInverter = true
          } else {
            this.popoverShowInverter = false
          }
          this.popoverTop = e.evt.clientY
          this.popoverLeft = e.evt.clientX
        })
        group.on('mouseenter', (e) => {
          // console.log('鼠标进入', group.id())
          setCursor(e)
        })
        group.on('mouseover', (e) => {
          // console.log('鼠标滑动', e.evt.clientX, e.evt.clientY)
          if (!this.popoverStatus) {
            setCursor(e)
          }
        })
        group.on('mouseleave', (e) => {
          // console.log('鼠标离开', e)
          setCursor(e, 'default')
        })
      })
      this.stage.on('click', (e) => {
        // console.log(e, 'this.stage click')
        setCursor(e, 'default')
        this.popoverStatus = false
        this.popoverData = {}
      })
      this.stage.on('dragmove', (e) => {
        // console.log('dragmove')
        this.popoverStatus = false
        this.popoverData = {}
      })
    },
    handleZoom(evt) {
      // const max = 4 // 放大最大的比例
      // const min = 0.5 // 缩小最小的比例
      // const step = 0.07 // 每次缩放的比例

      // const x = evt.offsetX
      // const y = evt.offsetY

      // const offsetX =
      //   ((x - this.layer.offsetX()) * this.layer.scaleX()) /
      //     (this.layer.scaleX() - step) -
      //   (x - this.layer.offsetX())
      // const offsetY =
      //   ((y - this.layer.offsetY()) * this.layer.scaleY()) /
      //     (this.layer.scaleY() - step) -
      //   (y - this.layer.offsetY())

      // if (evt.wheelDelta) {
      //   if (evt.wheelDelta > 0) {
      //     // 放大
      //     if (this.layer.scaleX() < max && this.layer.scaleY() < max) {
      //       this.layer.scaleX(this.layer.scaleX() + step)
      //       this.layer.scaleY(this.layer.scaleY() + step)
      //       this.layer.move({ x: -offsetX, y: -offsetY }) // 跟随鼠标偏移位置
      //     }
      //   } else {
      //     // 缩小
      //     if (this.layer.scaleX() > min && this.layer.scaleY() > min) {
      //       this.layer.scaleX(this.layer.scaleX() - step)
      //       this.layer.scaleY(this.layer.scaleY() - step)
      //       this.layer.move({ x: offsetX, y: offsetY }) // 跟随鼠标偏移位置
      //     }
      //   }
      // }
      const max = 4 // 放大最大的比例
      const min = 0.5 // 缩小最小的比例
      const step = 0.07 // 每次缩放的比例
      let x = this.defaultConfig.scaleX
      let y = this.defaultConfig.scaleY
      if (evt.wheelDelta > 0) {
        // 放大
        x += step
        y += step
        if (x >= max) x = max
        if (y >= max) y = max
      } else {
        // 缩小
        x -= step
        y -= step
        if (x <= min) x = min
        if (y <= min) y = min
      }
      this.defaultConfig.scaleX = x
      this.defaultConfig.scaleY = y

      this.stage.scale({
        x: x,
        y: y
      })
    },
    handleResize() {
      if (this.stage) {
        this.stage.destroy()
        this.initGraph()
        this.initPoints()
        this.render()
        this.eventListen()
      }
    },
    // 对接口数据转换函数
    transformData(data1) {
      const data2 = []

      data1.forEach((item1) => {
        const newItem2 = {
          inventerId: item1.inventerId,
          inventerNum: item1.inventerNum,
          inventerSnCode: item1.inventerSnCode,
          inventerModel: item1.inventerModel,
          cap: item1.inventerCap,
          name: item1.inventerName,
          optimizerRealList: []
        }

        item1.optimizerRealList.forEach((optimizer1) => {
          const optimizerNum = optimizer1.optimizerNum
          optimizer1.optimizerChanelList.forEach((channel1) => {
            const newOptimizer = {
              ...channel1,
              inventerId: item1.inventerId,
              inventerNum: item1.inventerNum,
              inventerSnCode: item1.inventerSnCode,
              optimizerName: optimizer1.optimizerName,
              optimizerNum: optimizerNum,
              optimizerSncode: optimizer1.optimizerSncode,
              optimizerModel: optimizer1.optimizerModel,
              cap: channel1.cap,
              channelNo: channel1.channelNo,
              channelNum:
                item1.inventerNum +
                '.' +
                optimizerNum +
                '.' +
                channel1.channelNo,
              timestamp: channel1.timestamp,
              status: channel1.status
            }
            newItem2.optimizerRealList.push(newOptimizer)
          })
        })

        data2.push(newItem2)
      })

      return data2
    }
  }
}
实际效果

实际效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 2 中使用 TypeScript(TS)编写计算属性(computed)与使用 JavaScript(JS)是类似的。下面是一个示例: ```typescript // 导入Vue和Component装饰器 import Vue from 'vue'; import Component from 'vue-class-component'; // 使用@Component装饰器定义组件 @Component export default class MyComponent extends Vue { // data属性 message: string = 'Hello World'; // 计算属性 get reversedMessage(): string { return this.message.split('').reverse().join(''); } // 监听计算属性的变化 @Watch('reversedMessage') onReversedMessageChange(value: string, oldValue: string) { console.log(`reversedMessage changed from ${oldValue} to ${value}`); } } ``` 在上面的示例中,我们使用`@Component`装饰器将类声明为一个 Vue 组件。然后,我们定义了一个名为`message`的数据属性和一个名为`reversedMessage`的计算属性。`reversedMessage`计算属性会根据`message`的值计算出一个新的值。 我们还可以使用`@Watch`装饰器来监听计算属性的变化。在上面的示例中,我们定义了一个名为`onReversedMessageChange`的方法,并用`@Watch('reversedMessage')`装饰器将其与`reversedMessage`计算属性关联起来。当`reversedMessage`发生变化时,该方法会被调用。 需要注意的是,为了让 TypeScript 正确地推断类型,我们需要将`vue-class-component`库安装为项目的依赖。你可以使用以下命令进行安装: ``` npm install vue-class-component ``` 这样,你就可以在 Vue 2 中使用 TypeScript 编写计算属性了。希望能对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值