Vue
vue 开发技巧
vue 相关 http 相关 webpack 相关 less 相关 vue 相关 1. vue splice 数组,数据删除了,但是没有 patch 到 dom 中 splice 删除数组,数据确实改变了,但是 dom 没有删除,或者 dom 删除的位置不对 添加一个唯一的 key 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,V…
vue 相关 http 相关 webpack 相关 less 相关 vue 相关 1. vue splice 数组,数据删除了,但是没有 patch 到 dom 中 splice 删除数组,数据确实改变了,但是 dom 没有删除,或者 dom 删除的位置不对 添加一个唯一的 key 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,V…
场景:splice 删除数组,数据确实改变了,但是 dom 没有删除,或者 dom 删除的位置不对
解决方法:添加一个唯一的 key
原理:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的唯一 id。
场景:通过下标改数组,修改数组长度,直接给对象添加属性,数据没有更新解决方法
针对数组
1、Vue.set(item,index,value)
2、使用数组的 splice,push,pop,unshift,shift 等方法
针对对象
1、Vue.set(object, key, value)
<!-- 绑定字符串不需要加冒号 -->
<Component message="hello" />
<!-- 布尔属性省略值时默认为 true -->
<Component visible />
<!-- 绑定无参函数事件不用加括号,并且传递了event对象 -->
<button @click="onClick">按钮</button>
检查 webpack中config 文件中的 assetsPublicPath 是否设置为'/'而不是'./'
可以参考之前写的组件通信的 6 种方式
通过 ref 属性,父组件调用子组件的方法,把要传的数组作为参数传给子组件,子组件获取该参数,并使用
watch 监听并赋值
// 缺点
// 所有函数和原型成员会被有意忽略,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;
}
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值了。
应用场景:通过指定改变样式<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;
}
});
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。
众所周知,使用 vuex 可以实现跨组件的数据状态共享,但是使用 vuex 毕竟要引入一个包,对项目的体积有影响,为了避免代码体积,可以在小项目中使用
Vue.observable实现跨组件状态共享



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


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


// 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)动态路由刷新后,参数会无效,带参数跳转刷新后参数有效
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];
});
}
// 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
应用场景:vue 单页中,请求不同源的接口,导致了跨域问题
解决方法:在 webpack 中设置如下参数
proxyTable: {
"/api": {
target: "http://example.com",
changeOrigin: true,
pathRewrite: {
"^/api": ""
}
}
}
/* autoprefixer: off */
-webkit-box-orient: vertical;
/* autoprefixer: on */
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
}
});
应用场景:引入了一个第三方 UI 库,比如 element UI,想改第三方库的样式// less
.parent /deep/ .child {
/* ... */
}
/* css */
.parent >>> .child {
/* ... */
}
// common是src中定义的文件夹
// common是个alias
background: url(~common/images/icon-tips2.png) no-repeat center / 100%;
暂无评论
确认操作
请再次确认编辑图片
待上传图片 (剩余 0 张)
项目详情
确认评论邮箱
邀请制评论