Vue2 个人记录

MuYan2021-12-21VueVue

组件的插槽问题

可以在组件内通过 $slots 判断是否有默认(default)插槽或自定义具名插槽。相关文档open in new window

例如:

<template>
  <!--demo 组件-->
  <!-- 不存在默认插槽-->
  <div v-if="!$slots.default || !$slots.$default"></div>
  <!-- 存在默认插槽-->
  <slot v-else />
  <!-- 不存在具名(demo)插槽-->
  <div v-if="!$slots.demo || !$slots.$demo"></div>
  <!-- 存在具名(demo)插槽-->
  <slot v-else />

  <!--父页面或父组件使用demo组件-->
  <demo>
    <!--默认插槽-->
    这是默认插槽
    <!--(demo)具名插槽-->
    <div slot="dmeo">这是demo具名插槽</div>
  </demo>
</template>

computed 的几种使用方法

  1. 使用基础的 gettteropen in new window 属性 (Get)
<template>
  <div>{{ demo }}</div>
</template>
<script>
export default {
  data() {
    return {
      price: 1000,
    };
  },
  computed: {
    demo() {
      return "测试";
    },
  },
};
</script>
  1. 使用 settteropen in new window 属性 (Set)
<template>
  <div>
    <div @click="change">{{ text }}</div>
    {{ demo }}
  </div>
</template>
<script>
export default {
  data() {
    return {
      text: "测试",
    };
  },
  computed: {
    demo: {
      // getter
      get: function() {
        console.log("调用了getter属性", this.text);
        return `demo====>${this.text}`;
      },
      // setter
      set: function(n) {
        console.log("调用了settter属性", n);
        this.text = n;
      },
    },
  },
  methods: {
    change() {
      this.demo = "被点击了";
    },
  },
};
</script>
  1. 传参使用
<template>
  <div>{{ demo("测试") }}</div>
</template>
<script>
export default {
  data() {
    return {
      price: 1000,
    };
  },
  computed: {
    demo() {
      return (n) => {
        console.log(n); // 测试
        return n;
      };
    },
  },
};
</script>

watch 的几种用法

<script>
export default {
  data() {
    return {
      demo: {
        id: 0
      },
      show: false
    };
  },
  watch: {
    // 普通监听
    show (oldVal,newVal) {
      console.log(oldVal,newVal)
    },
    // 对象属性监听:监听对象的指定属性
    "demo.id" (oldVal,newVal) {
      console.log(oldVal,newVal)
    },
    // 对象深度监听:对象内属性变化都会执行
    demo:  {
      handler(oldVal,newVal){
        console.log(oldVal,newVal)
      },
      immediate: true, // 首次绑定的时候,是否执行handler
      deep: true
    },
};
</script>

v-if\v-show 区别

v-if: 支持 <template> 语法。

v-show: 不支持 <template> 元素,也不支持 v-else。

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

keep-alive 组件

如果 keep-alive 内的 router-view 做了 v-if 判断,由于 v-if 的特性,在判断不成立的情况下,会销毁 router-view 。如果不想销毁,并继续缓存,建议通过 v-show 实现该功能

解决 v-html 指令潜在的 xss 攻击

在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html,永不用在用户提交的内容上。来自:v-html 相关文档open in new window

解决办法:

  • 使用一个 xss 的 npm 包来过滤 xss 攻击代码。

  • 使用该方法后默认会去除 v-html 插入内容的 class、style 样式。但可以通过包裹 v-html 的元素进行样式重定义。

<!-- 包裹层的 style\class 依旧有效,因为过滤的只是 v-html 插入内容。 -->
<div style="font-size: 18px;" class="demo-wrap" v-html="xxxxx"></div>
npm install xss --save
  • 在 main.js 引入 xss 包并挂载到 vue 原型上
// main.js
import xss from "xss";
Vue.prototype.xss = xss;
  • 在 vue.config.js 或 vue-loader.config.js 中覆写 html 指令
// vue.config.js
module.exports = {
  chainWebpack: (config) => {
    config.module
      .rule("vue")
      .use("vue-loader")
      .loader("vue-loader")
      .tap((options) => {
        options.compilerOptions.directives = {
          html(node, directiveMeta) {
            (node.props || (node.props = [])).push({
              name: "innerHTML",
              value: `xss(_s(${directiveMeta.value}))`,
            });
          },
        };
        return options;
      });
  },
};
// vue-loader.config.js
module.exports = {
  compilerOptions: {
    directives: {
      html(node, directiveMeta) {
        (node.props || (node.props = [])).push({
          name: "innerHTML",
          value: `xss(_s(${directiveMeta.value}))`,
        });
      },
    },
  },
};

...不定时更新

参考文档:Vue 文档open in new window

上次更新 2026/6/23 11:49:15
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8