vue 相关 http 相关 webpack 相关 less 相关 vue 相关 1. vue splice 数组,数据删除了,但是没有 patch 到 dom 中 splice 删除数组,数据确实改变了,但是 dom 没有删除,或者 dom 删除的位置不对 添加一个唯一的 key 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,V…

vue 相关


1. vue splice 数组,数据删除了,但是没有 patch 到 dom 中

  • 场景:splice 删除数组,数据确实改变了,但是 dom 没有删除,或者 dom 删除的位置不对

  • 解决方法:添加一个唯一的 key

  • 原理:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的唯一 id。

2. 通过数组下标给数组添加元素、修改数组长度或者直接对对象的属性的添加或删除,数据没有更新

  • 场景:通过下标改数组,修改数组长度,直接给对象添加属性,数据没有更新
解决方法
针对数组
1、Vue.set(item,index,value)
2、使用数组的 splice,push,pop,unshift,shift 等方法
针对对象
1、Vue.set(object, key, value)

3. vue 中属性与事件绑定的一些小技巧

<!-- 绑定字符串不需要加冒号 -->
<Component message="hello" />
<!-- 布尔属性省略值时默认为 true -->
<Component visible />
<!-- 绑定无参函数事件不用加括号,并且传递了event对象 -->
<button @click="onClick">按钮</button>

4. vue 背景图打包之后访问路径错误问题

检查 webpack中config 文件中的 assetsPublicPath 是否设置为'/'而不是'./'

5. 父组件如何向子组件动态传值

可以参考之前写的组件通信的 6 种方式

  • 通过 ref 属性,父组件调用子组件的方法,把要传的数组作为参数传给子组件,子组件获取该参数,并使用

  • watch 监听并赋值

6. vue 中 实现对象的深拷贝

  • 暴力解决
// 缺点
// 所有函数和原型成员会被有意忽略,JSON.parse(JSON.stringfy(X)),其中X只能是Number, String, Boolean, Array, 扁平对象,即那些能够被 JSON 直接表示的数据结构
JSON.parse(JSON.stringify(data));
  • 优雅解决
function deepClone(data) {
  var obj;
  if (Object.prototype.toString.call(data).slice(8, -1) === "Array") {
    obj = [];
  } else if (Object.prototype.toString.call(data).slice(8, -1) === "Object") {
    obj = {};
  } else {
    //不再具有下一层次
    return data;
  }
  if (Object.prototype.toString.call(data).slice(8, -1) === "Array") {
    for (var i = 0, len = data.length; i < len; i++) {
      obj.push(deepClone(data[i]));
    }
  } else if (Object.prototype.toString.call(data).slice(8, -1) === "Object") {
    for (var key in data) {
      obj[key] = deepClone(data[key]);
    }
  }
  return obj;
}

7. vue 几种常用的指令

1、v-model 双向绑定,修饰符trim:去除表单value中首位空格;number:字符串转为数字;lazy:化同步双向为change双向

2、v-show,v-if,v-else-if,v-else: v-if等则通过判断进行物理留去,v-else与v-else-if必须紧跟于v-if后;

3、v-for:遍历数组或者对象并进行渲染,遍历单项可有三个参数key,value,index

4、v-bind:用于响应式绑定属性和特性

5、v-on:于绑定事件

6、v-text, v-html:  v-text  等价于{{}} v-html 可以绑定dom结构 二者可以解决网速慢导致的{{]}闪动问题

7、v-once:在第一次DOM时进行渲染,渲染完成后视为静态内容,跳出以后的渲染过程

8、v-cloak:在vue渲染完指定的整个DOM后才进行显示。它必须和CSS样式一起使用

9、v-pre:在模板中跳过vue的编译,直接输出原始值。就是在标签中加入v-pre就不会输出vue中的data值了。

8. 一个实用的自定义指令

  • 应用场景:通过指定改变样式
<p v-value='{color:"#000",fontSize:"30px"}'>hello</p>;

Vue.directive("value", {
  update(el, binding) {
    el.style.background = "red";
    el.style.color = binding.value.color;
    el.style.fontSize = binding.value.fontSize;
  }
});

9. vue、react 和 angular 的区别

1.与AngularJS的区别
相同点:
都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。

不同点:
AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。

2.与React的区别
相同点:
React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。

不同点:
React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。

10. 使用 Observable API 实现跨组件数据状态共享

众所周知,使用 vuex 可以实现跨组件的数据状态共享,但是使用 vuex 毕竟要引入一个包,对项目的体积有影响,为了避免代码体积,可以在小项目中使用 Vue.observable 实现跨组件状态共享

  • store.js

store

  • about.vue

about

  • home.vue

home

11. 作用域插槽

作用域插槽,适用于:User 的父组件负责布局,User 组件负责数据处理,改动布局找 A,改动数据找 B

  • user.vue

user

  • about.vue

about

12. 函数式组件

函数式组件:无状态,无实例,内部没有生命周期,适合用来只依赖外部数据变化的组件

  • list.vue

list

  • about.vue

about

13. vue-router 的传参方式:带参数和动态路由

// 1、带参数跳转,不需要在路由里面设置参数,跳转结果:localhost:8080/index?id=1
this.$router.push({ path: "/index", query: { id: 1 } });
// 2、动态路由
// 需要在router.js中设置匹配参数
{
  path: "/index/:id",
  name: Index,
  component: Index
}
// 动态路由,跳转结果:localhost:8080/index/1
this.$router.push({ name: "Index", params: { id: 1 } });
// 3、获取参数
this.$route.query
this.$route.params
// 4、两者区别:1)动态路由传的是name,带参数跳转是path;2)动态路由需要在路由文件写好匹配参数,带参数跳转不用;
//             3)动态路由的参数类似一个子路由,带参数跳转类似url参数;4)动态路由刷新后,参数会无效,带参数跳转刷新后参数有效

http 相关


1. async/await 如何优雅的捕获异常

export default {
  methods: {
    async getData() {
      const [err, result] = await catchError(httpGetData());
      if (err) {
        throw new Error("接口异常");
        return;
      }
      console.log(result);
    }
  }
};
export function catchError(promise) {
  if (!promise || !Promise.prototype.isPrototypeOf(promise)) {
    return new Promise((resolve, reject) => {
      reject(new Error("requires promises as the param"));
    }).catch((err) => {
      return [err, null];
    });
  }
  return promise
    .then(function() {
      return [null, ...arguments];
    })
    .catch((err) => {
      return [err, null];
    });
}

2. vue 中如何优雅的使用 axios

// index.js
import _axios from "./axios";
export default {
  getData() {
    return _axios("static/index.json");
  }
};
// axios.js
import axios from "axios";
// 需要使用代理来解决跨域问题
axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
axios.defaults.timeout = 20000;

// Add a request interceptor
axios.interceptors.request.use(
  (config) => {
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);
export default async (url = "", params = {}, method = "get", isUpload = false) => {
  method = method.toLowerCase();
  if (method === "get") {
    let paramArr = [];
    for (let [key, value] of Object.entries(params)) {
      paramArr.push(key + "=" + value);
    }
    if (paramArr.length > 0) {
      url += "?" + paramArr.join("&").replace(/#/g, "%23");
    }
    return new Promise((resolve, reject) => {
      axios
        .get(url)
        .then(
          (response) => {
            resolve(response.data);
          },
          (err) => {
            reject(err);
          }
        )
        .catch((error) => {
          reject(error);
        });
    });
  } else if (method === "post") {
    let config = {};
    if (isUpload) {
      config = {
        headers: {
          "Content-Type": "multipart/form-data"
        }
      };
    }
    return new Promise((resolve, reject) => {
      axios
        .post(url, params, config)
        .then(
          (response) => {
            resolve(response.data);
          },
          (err) => {
            reject(err);
          }
        )
        .catch((error) => {
          reject(error);
        });
    });
  } else if (method === "put") {
    return new Promise((resolve, reject) => {
      axios
        .put(url, params)
        .then(
          (response) => {
            resolve(response.data);
          },
          (err) => {
            reject(err);
          }
        )
        .catch((error) => {
          reject(error);
        });
    });
  } else if (method === "delete") {
    return new Promise((resolve, reject) => {
      axios
        .delete(url)
        .then(
          (response) => {
            resolve(response.data);
          },
          (err) => {
            reject(err);
          }
        )
        .catch((error) => {
          reject(error);
        });
    });
  } else {
    let error = "传递的参数错误";
    return Promise.reject(error);
  }
};

webpack 相关

如果对 webpack 的基本使用还不太熟悉,可以看我之前写的webpack


1. vue 如何设置代理

  • 应用场景:vue 单页中,请求不同源的接口,导致了跨域问题

  • 解决方法:在 webpack 中设置如下参数

proxyTable: {
  "/api": {
    target: "http://example.com",
    changeOrigin: true,
    pathRewrite: {
      "^/api": ""
    }
  }
}

2. OptimizeCSSPlugin 误删-webkit-头的解决方法

  • 方法 1
/* autoprefixer: off */
-webkit-box-orient: vertical;
/* autoprefixer: on */
  • 方法 2
new OptimizeCSSPlugin({
  // 打包后要不要的.map文件
  cssProcessorOptions: config.build.productionSourceMap
    ? {
        // 避免 cssnano 重新计算 z-index
        safe: true,
        // map文件的行内样式
        map: {
          inline: false
        },
        autoprefixer: false
      }
    : {
        // 避免 cssnano 重新计算 z-index
        safe: true,
        autoprefixer: false
      }
});

less 相关


1. less 中的深度选择器

  • 应用场景:引入了一个第三方 UI 库,比如 element UI,想改第三方库的样式
// less
.parent /deep/ .child {
  /* ... */
}
/* css */
.parent >>> .child {
  /* ... */
}

2. .vue 文件中如何使用 background-url

// common是src中定义的文件夹
// common是个alias
background: url(~common/images/icon-tips2.png) no-repeat center / 100%;

暂无评论