这我哪会啊 2023-08-14 11:34 采纳率: 0%
浏览 22
已结题

Vue全局指令改变表单样式的bug

事情是这样的,我接到的需求是要做一个表单的动态效果,预期效果如图:

img

也就是更改了之后会把对应表单的标签变成红色,现在出现的问题是,当我操作其他数据的时候,即使我没有做更改他也会报错误高亮

img

img

这是全局指令的相关代码

export default {
  bind(el, binding, vnode) {
    resetInitialState(vnode); // 重置初始状态
  },
  inserted(el, binding, vnode) {
    vnode.context.$nextTick(() => {
      initializeState(el, binding, vnode);
    });
  },
  update(el, binding, vnode, oldVnode) {
    if (binding.value !== binding.oldValue) {
      vnode.context.$nextTick(() => {
        let id = vnode.context.form.id
        let newVal = binding.value
        let oldValue = binding.oldValue

        let edited = false
        if (id && newVal !== undefined && oldValue !== undefined) {
          if (newVal !== oldValue) {
            edited = true
          }
        }
        updateLabelStyle(el, edited);
        initializeState(el, binding, vnode);
      });
    }
  },
  unbind(el, vnode) {
    resetInitialValues(vnode); // 重置初始值
    if (el._observer) {
      el._observer.disconnect();
    }
  },
};

function updateLabelStyle(el, edited) {
  const labelElement = el.querySelector('label');
  if (labelElement) {
    edited ? labelElement.classList.add('edited-label') : labelElement.classList.remove('edited-label');
  }
}

function resetInitialState(vnode) {
  vnode.context.initialValues = {};
}

function resetInitialValues(vnode) {
  const instanceUid = vnode.context._uid;
  if (vnode.context.initialValues && vnode.context.initialValues[instanceUid]) {
    delete vnode.context.initialValues[instanceUid];
  }
}

function initializeState(el, binding, vnode) {
  const propName = binding.expression;
  const instanceUid = vnode.context._uid;
  let initialValues = vnode.context.initialValues;
  if (!initialValues) {
    vnode.context.initialValues = initialValues = {};
  }

  if (!initialValues[instanceUid]) {
    initialValues[instanceUid] = {};
  }

  const isNewForm = binding.modifiers.new;
  if (isNewForm) {
    initialValues[instanceUid][propName] = null;
  } else if (initialValues[instanceUid][propName] === undefined) {
    initialValues[instanceUid][propName] = JSON.stringify(binding.value);
  }

  const updateLabelStyle = (edited) => {
    const labelElement = el.querySelector('label');
    if (labelElement) {
      edited ? labelElement.classList.add('edited-label') : labelElement.classList.remove('edited-label');
    }
  };

  const updateLabelColor = (newVal) => {
    let newValue = newVal === undefined || newVal === '' ? '' : JSON.stringify(newVal);
    updateLabelStyle(newValue !== initialValues[instanceUid][propName]);
  };

  updateLabelColor(binding.value);

  vnode.context.$watch(propName, (newVal) => {
    vnode.context.$nextTick(() => {
      updateLabelColor(newVal);
    });
  }, { deep: true });

  const updateLabelCallback = () => updateLabelColor(vnode.context[propName]);

  const classList = ['el-select', 'el-radio-group', 'el-input-number', 'el-checkbox-group', 'el-date-picker'];
  for (const className of classList) {
    if (el.classList.contains(className)) {
      el._observer = observeElement(el.querySelector(`.${className.split('-').slice(-1)[0]}`), updateLabelCallback);
      break;
    }
  }
}

function observeElement(element, callback) {
  if (element) {
    const observer = new MutationObserver(callback);
    observer.observe(element, {
      attributes: true,
      childList: true,
      subtree: true,
    });
    return observer;
  }
}

最好是能远程帮看一下

  • 写回答

10条回答 默认 最新

  • hyh123a 新星创作者: 编程框架技术领域 2023-08-14 11:48
    关注

    问题

    先确认下问题,
    也就是原本要求是:
    A标签对应内容修改的话,那么A标签变红色
    B/C/D其余标签没有内容修改那么不变化

    现在的问题是:
    A标签修改内容后,A标签变色
    但是没有修改的B标签也变色了?

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 8月14日
  • 创建了问题 8月14日