优秀的编程知识分享平台

网站首页 > 技术文章 正文

vue+element-ui 纯干货 可码 有点乱

nanyue 2024-08-10 18:39:15 技术文章 6 ℃

***论阅读源码的重要性***

/*解决https下面无法加载http路径图片的问题

<meta http-equiv ="Content-Security-Policy" content="upgrade-insecure-requests">

es6新语法

箭头函数

在传统函数的写法上,去掉function关键字, 并且在参数列表的()与{} 函数体之间加上=>,若该函数没有参数,小括号不能省略。

var foo = function(){};

var foo =()=> {};

foo();

模板字符串

而在ES6的语法当中,采用一对反引号``来表示字符串,称之为模板字符串。

1、模板字符串内部可以随意的回车、换行、加空格,均有效,不需要另外考虑字符串拼接的问题。

2、在模板字符串内部可以用${变量名}的方式来直接取变量的值,此时在模板字符串内部,变量与字符串之间不需要用连字符+号进行拼接。

var str1 = `ab ca`; var a = 'hello'; console.log(str1); console.log(`${a} world`); //ab ca // hello world

const和let var之后都可以被ES6语法当中的const和let所代替。

const:用const定义的变量,之后不允许再对其赋值(赋值也不起作用);

const a = 10;

a = 20;

console.log(a); // 10

如果const定义的是一个对象,该对象不允许再变,但该对象当中的某个属性所对应的属性值是允许再被改变赋值的。

const b={a:10};

console.log(b.a); // 10

b.a=20;

console.log(b.a); // 20

如果定义一个变量,该变量的值之后不会再发生变化,可以使用const, 一般我们把node当中载入的模块使用const定义的变量来接收,防止以后再对该变量进行赋值,使代码更加严谨。

let:使用let定义变量相当于定义了一个局部作用域变量,只会影响当前这个作用域。

如果定义一个变量,该变量的取值之后是会发生变化的,即用let来定义。避免使用var使得变量的污染域变大。

V8对于ES6的语法的支持情况分为三个级别:根本不支持、直接支持、严格模式下支持。对于const和箭头函数及模板字符串都是直接支持的,而let关键字为严格模式下支持。若直接使用会出现如下的报错信息。

'use strict';

let a=10;

a=20;

console.log(a); // 20

javascript中的作用域和闭包

任何js代码在执行前都有大量工作要做,如果只依靠引擎自己,其实很难做到,需要用到引擎的一个得力助手:作用域

作用域为引擎提供了环境内每一个标识符的位置信息,引擎依赖这些信息可以迅速查找到他们定义的位置。标识符的位置信息,是你在写代码时将标识符写在哪里来决定的,在词法分析阶段(编译的第一个阶段),这些标识符的位置信息就会以有序列表的形式保存到环境的scope属性中(也就是作用域),以供引擎使用。也可以简单理解为,作用域里面保存的信息,在你写代码的时候已经决定了,而且会一直保持这个作用域不变。



作用域的查找规则

1、查找标识符的过程会始终从当前作用域开始,然后逐级的向外层嵌套的作用域展开,知道找到标识符,或抵达最外层的作用域(全局作用域)为止,如果找不到标识符,通常会导致错误发生。(从里向外查找)

2、每个执行环境都可以进入到外层作用域中查找标识符,但不能进入到内层作用域中查找标识符。



闭包原理:

https://www.imooc.com/article/285474?block_id=tuijian_wz

1、southtree代码管理工具 gitlab代码管理平台的使用

2、阿里云云效平台使用rdc、工作任务分配管理、bug修改

3、电销后台管理系统

4、vue 组件化开发

5、vue filter过滤器、find函数、map、set

6、h5与app联调 (navigator 对象包含有关浏览器的信息)** app && h5混合开发

判断安卓和ios环境:isAndroid: navigator.userAgent.includes('Android'),

isIOS: navigator.userAgent.includes('OS')

安卓: 判断navigator.userAgent.includes('yangcheJS') 是否存在yangcheJS

存在则与app匹配成功 => 赋值:this.mobilePhone = JSON.parse(window.yangcheJS.getUserPhone())

h5向app传值: (均为app端定义的方法,h5则直接调用app方法传值)

let arrData = { payLink: this.body }

window.yangcheJS.WebViewJavascriptBridge('RequestPayment', JSON.stringify(arrData), '', 'onlinePay', '')

app回调h5的方法 将h5的方法暴露到window上

let me = this;

window['getStatus'] = (status) => {

me.getStatus(status);

}

getStatus()

IOS:

IOS:window.webkit.messageHandlers.getUserPhone.postMessage('111');先向ios发送一串指令(类似注册)(getUserPhone为约定方法)

后接收ios传过来的数据(同安卓)暴露一个getUserPhone()方法method里接收数据

7、vue图片前端签名直传阿里云oss

接口获取阿里云服务端 签名、policy、OSSAccessKeyId

const x2js = require('x2js');

let formData = new FormData()

// 参数顺序不能变

formData.append('key', '${filename}') // key默认${filename}

formData.append('policy', this.aliForm.policy)

formData.append('OSSAccessKeyId', this.aliForm.ossAccessKeyId)

formData.append('success_action_status', '201') // 默认201状态*

formData.append('Signature', this.aliForm.signature)

formData.append('file', file.raw)

this.$http({

method: 'post',

url: 'https://c1-yangche.oss-cn-hangzhou.aliyuncs.com',

data: formData

}).then((resd) => {

let myheadInfo = this.$x2js.xml2js(resd.data)

console.log(resd)

this.ruleForm.headImg = myheadInfo.PostResponse.Location

}).catch((err) => {

})

8、promise.all/async await 异步接口并发处理

9、encodeURI(string)对字符串编码,encodeURIComponent(string)对字符串解码(特殊字符:冒号、正斜杠、问号和井字号)

10、vue 引入百度地图获取定位 解决new BMap未定义 (高德地图就是个垃圾)

11、不是为了vue写的插件不支持Vue.use()加载方式 使用Vue.prototype挂载到vue原型上添加全局属性和方法

12、组件之间传值方法

父组件 =》 子组件

页面:<userManage-box @msg=“getMsg :msg=msg></userManage-box>

父组件定义 component:{"userManage-box": () => import("./userManage-box")} 传值 :msg=msg

子组件使用prop接收 接收值类型:Array String Number。。

子组件 =》 父组件

this.$emit(msg,getMsg) msg:方法名字,getMsg:要传出的值

父组件定义方法接收 @msg=“getMsg” method里getMsg(e)接收子组件传过来的值

兄弟组件之间通过父组件通信

13、vue webSocket 通信

https://www.jianshu.com/p/938004c22ed9

14、微信web-view(小程序内置h5)

h5端:引入微信jssdk/使用npm安装jssdk

<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>

npm install weixin-js-sdk --save

import wx from 'weixin-js-sdk';

Vue.prototype.$wx = wx;

h5向小程序传值

mounted(){

wx.miniProgram.getEnv(res => {

this.inLiteApp = res.miniprogram

})

}

方法: {

if (this.inLiteApp == true) {

wx.miniProgram.navigateTo({

url: '/pages/payment/index/main?orderId=' + this.detail.orderId + '&orderCode=' + this.detail.orderCode + '&amount=' + this.detail.stats[2].value

})

}

}

小程序接收h5传过来的值(h5传过来的值直接从optios里取)

async onLoad(options) {

this.payInfo = options

}

小程序向h5传值

<web-view :src="webviewUrl" @message="postMessage"/>

onLoad(options) {

// params为其他页面或者接口里接收到的数据

const params = {

userId: this.userId,

ticket: this.ticket,

appTicket: this.appTicket

}

this.webviewUrl = `https://mini.yangche51.com/#/home?parmas=${this.params}`;

}

h5接收小程序传过来的值

created() {

wx.miniProgram.getEnv(res => {

if (res.miniprogram) { //判断微信环境

const queryUrl = this.getRequest()

let urlParams = Object.assign(queryUrl, this.$route.query) //参数合并 Object.assign()是浅拷贝

let wxParmas = JSON.parse(queryUrl.parmas)

console.log('我接收到的参数', wxParmas)

document.cookie = "app_ticket=" + wxParmas.appTicket; //接收到的微信参数放入cookie里

this.$store.dispatch("auth/saveToken", { 调取store里的user.js的auth/saveToken方法,更新数据

token: wxParmas.ticket,

remember: 365

})

}

})

},

methods: {

getRequest() {

var url = decodeURIComponent(location.search); // 对参数解码获取到'#'后面的参数

var theRequest = new Object();

if (url.indexOf("?") != -1) { // 查找是否包含'?'

var str = url.substr(1); // 截取字符串

var strs = str.split("&"); // 分割字符串

for(var i = 0; i < strs.length; i ++) {

theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]); // unescape()函数解码字符串

}

}

return theRequest; //返回结果

},

}

15、md5密码加密

let password = md5(this.password);默认小写32位

let password = md5(this.password).toUpperCase(); 大写32位

16、关于vue深拷贝与浅拷贝的思考

假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝;

假设B复制了A,当修改A时,如果B没变,那就是深拷贝

深拷贝的实现



*递归复制所有层级属性

function deepClone(obj){

let objClone = Array.isArray(obj)?[]:{};

if(obj && typeof obj==="object"){

for(key in obj){

if(obj.hasOwnProperty(key)) {

// 判断ojb子元素是否为对象,如果是,递归复制

if(obj[key]&&typeof obj[key] ==="object"){

objClone[key] = deepClone(obj[key]);

}else{

//如果不是,简单复制

objClone[key] = obj[key];

}

}

}

}

return objClone;

}

let a=[1,2,3,4],

b=deepClone(a);

a[0]=2;

console.log(a,b);

*JSON对象的parse和stringify实现

function deepClone(obj) {

let _obj = JSON.stringify(obj),

objClone = JSON.parse(_obj);

return objClone

}

let a=[0,1,[2,3],4],

b=deepClone(a);

a[0]=1;

a[2][0]=1;

console.log(a,b);

17、vue操作数组的几种方法(push()、pop()、shift()和unshift()实现数组的增删操作、sort()和 reverse()对数组项进行排序操作)

concat():先给当前数组创建一个副本,然后将接收到的参数添加到这个副本(数组)的末尾,最后返回一个新的数组

var arr = [`大漠`,'30','W3cplus'];

console.log(arr); // ["大漠", "30", "W3cplus"]

var arr2 = arr.concat('Blog','2014');

console.log(arr2); // ["大漠", "30", "W3cplus", "Blog", "2014"]

**concat()方法是在数组的副本上进行操作并返回新构建的数组,所以并不会影响到原来的数组。

https://blog.csdn.net/qq_35192741/article/details/80655464

18、解构赋值

对象的解构赋值用于从一个对象取值,相当于将所有可遍历的、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };

x // 1

y // 2

z // { a: 3, b: 4 }

19、Promise / vue中axios的封装

promise是异步编程的一种解决方案,比传统异步解决方案【回调函数】和【事件】更合理、更强大

安装:axios npm install axios

引入:在项目的src目录中新建一个request文件夹,然后在里面新建一个http.js和api.js文件。http.js文件用来封装axios,api.js用来统一管理接口

// 在http.js中引入axios

import axios from 'axios'; // 引入axios

import QS from 'qs'; // 引入qs模块,用来序列化post类型的数据,后面会提到

// vant的toast提示框组件,大家可根据自己的ui组件更改。

import { Toast } from 'vant';

环境的切换:项目环境中可能有开发、测试、生产环境,我们通过node的环境变量来匹配我们的默认接口url前缀。axios.defaults.baseURL可以设置axios的默认请求地址

// 环境的切换

// 环境的切换

if (process.env.NODE_ENV == 'development') {

axios.defaults.baseURL = 'https://www.baidu.com';}

else if (process.env.NODE_ENV == 'debug') {

axios.defaults.baseURL = 'https://www.ceshi.com';

}

else if (process.env.NODE_ENV == 'production') {

axios.defaults.baseURL = 'https://www.production.com';

}

设置请求超时:通过axios.default.timeout设置默认的请求超时时间。例如超过10s,就会告知用户当前接口请求超时,请刷新等

axios.default.timeout = 10000;

post请求头的设置:post请求的时候,我们需要加上一个请求头,所以可以在这里进行一个默认的设置,即设置post的请求头为application/x-www-form-urlencoded;charset=UTF-8

axios.default.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';

请求拦截:有些请求是需要用户登录之后才能访问的,或者post请求时我们需要序列化我们提交的数据,这时候我们可以在请求的发送之前进行拦截,从而进行我们想要的操作

//先导入vuex,因为我们要使用到里面的状态对象

//vuex的路径根据自己的路径去写

import store from '@/store/index';

//请求拦截器

axios.interceptors.request.use(

config => {

// 每次发送请求之前判断vuex中是否存在token

// 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况

// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断

const token = store.state.token;

token && (config.headers.Authorization = token);

return config;

},

error => {

return Promise.error(error);

}

)

token:一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地,然后用户每次在进入页面的时候(main.js中),会首先从本地存储中读取token,如果token存在则说明用户已经登录过了,则更新vuex中的token状态。然后,在每次请求接口的时候都会在header中带上token,

后台就可以根据你带的token判断你的登录是否过期,如果没有携带,则说明没有登录过。

响应拦截:服务器返给我们的数据,我们在拿到之前根据后台返回的状态码对他进行一些处理(200 成功,401 未登录, 403 token过期, 404 请求不存在, 其他直接抛出错误提示)

//响应拦截器

axios.interceptors.response.use(

response => {

// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据

// 否则的话跑出错误

if(response.status === 200) {

return Promise.resolve(response);

} else {

return Promise.reject(response);

}

},

//状态码不是2开头的情况

//这里可以跟你们后台开发人员协商好统一的错误码

//然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等

// 下面列举几个常见的操作,其他需求可自行扩展

error => {

if(error.response.status) {

switch (error.response.status) {

//401:未登录

//未登录则跳转登录页面,并携带当前页面的路径

// 在登录成功后返回当前页面,这一步需要在登录页面操作

case 401:

router.replace({

path: '/login',

query: {

redirect: router.currentRoute.fullPath

}

});

break;

//403 token过期

// 登录过期对用户进行提醒

// 清除本地token和清空vuex中的token对象

// 跳转登录页面

case 403:

Toast({

message: '登录过期,请重新登录',

duration: 1000,

forbidClick: true

});

//清除token

localStorage.removeItem('token');

store.commit('loginSuccess', null);

//跳转登录页面,并将要浏览的页面fullPath传过去,登陆成功后跳转需要访问的页面

setTimeout(() => {

router.replace({

path: '/login',

query: {

redirect: router.currentRoute.fullPath

}

});

}, 1000);

break;

//404请求不存在

case 404:

Toast({

message: '网络请求不存在',

duration: 1500,

forbidClick: true

});

break;

//其他错误,直接抛出错误提示

default:

Toast({

message: error.response.data.message,

duration: 1500,

forbidClick: true

});

}

return Promise.reject(error.response);

}

});

封装get方法和post方法


20、vuex (vue状态管理器)

解释:一个专为vue应用程序开发的状态管理模式 它集中式存储管理应用的所有组件的状态,而更改状态的唯一方法就是提交mutation

例:this.$store.commit('SET_VIDEO_PAUSE', video_pause), SET_VIDEO_PAUSE为mutations属性中定义的方法

五种状态和属性:State、Getter、Mutation、Action、Module(mapAction)

流程:页面通过mapAction异步提交事件到action。action通过commit把对应的参数同步提交到mutation。mutation会修改state里对应的值。最后通过getter把对应的值跑出去,在页面计算属性中通过mapGetter来动态获取state里的值

State的特性:存放数据的地方,类似一个仓库

当mutation修改了state里的数据的时候,会动态修改所有调用这个变量的所有组件里的值(若是store中的数据发生变化,依赖这个数据的组件就会实时更新)

Getter的特性:getter用来获取数据,mapGetter经常在计算属性中被使用(通常放在mixins里全局使用)

Mutation的特性:Action类似于mutation,不同在于:

Action提交的是mutation,而不是直接变更状态

Action可以包含任意异步操作

优势:1、响应式的数据管理 一个页面发生数据变化,动态的改变对应的页面,相比使用localStorage只能存储字符串数据格式,因此还得封装自己的写入写出,localStorage优势在于永久存储

1、多个组件依赖于同一状态时。

2、来自不同组件的行为需要变更同一状态。

21、typeOf {} //object 用于返回数据的数据类型

22、webpack(模块打包机)

是什么:webpack是一个打包模块化js的工具,分析你的项目结构,找到js模块以及其他的一些浏览器不能直接运行的拓展语言(scss,ts等),并将其打包为合适的格式以供浏览器使用。

23、vue前端性能优化

1、vue-router路由懒加载(按需加载页面,提高页面加载性能,提高用户体验)

export default new Router({

mode: 'history',

routes: [

{

path: '/',

component: resolve => require(['@/components/DefaultIndex'],resolve),

children: [

{

path: '',

component: resolve => require(['@/components/Index'],resolve)

},

{

path: '*',

redirect: '/Index'

}

]

})

2、webpack压缩图片(减少图片大小)

安装image-webpack-loader

npm install image-webpack-loader --save-dev

配置

在webpack.base.conf.js文件中引入配置

1: 引入:

require("image-webpack-loader")

2:配置:

module: {

rules: [

...(config.dev.useEslint ? [createLintingRule()] : []),

{

test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

loader: 'url-loader',

options: {

loader: 'image-webpack-loader',

options: {

bypassOnDebug: true,

}

}

},

或者也可配置为:

{

test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

use:[

{

loader: 'url-loader',

options: {

limit: 10000,

name: utils.assetsPath('img/[name].[hash:7].[ext]')

}

},

{

loader: 'image-webpack-loader',

options: {

bypassOnDebug: true,

}

}

]

}

3、取消额外打包的js文件

配置

在config/index.js文件里面修改

build:{}里面的productionSourceMap为false

4、打包后的js过大,将js打包多个文件

entry:{

main:'xxx.js'

}

plugins:{

new commonsChunkPlugin({

name:'commons',

minChunks:function(module){

// 下边return参考的vue-cli配置

// any required modules inside node_modules are extracted to vendor

return (

module.resource &&

/\.js$/.test(module.resource) &&

module.resource.indexOf(

path.join(__dirname, '../node_modules')

) === 0

)

}

}) ,

// 以下才是关键

new commonsChunkPlugin({

name:'charts',

chunks:['commons']

minChunks:function(module){

return (

module.resource &&

/\.js$/.test(module.resource) &&

module.resource.indexOf(

path.join(__dirname, '../node_modules')

) === 0 && ['jquery.js', 'highcharts.js','echarts'].indexOf( module.resource.substr(module.resource.lastIndexOf('/')+1).toLowerCase() ) != -1

)

}

})

}

5、去掉不必要的插件

plugins: [//webpack.config.jsnew webpack.optimize.UglifyJsPlugin({ warnings: false,

compress: {

join_vars: true,

warnings: false,

},

toplevel: false,

ie8: false,

]

6、gzip压缩

# 开启gzip

gzip on;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩

gzip_min_length 1k;

# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明

gzip_comp_level 2;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。

gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

# 是否在http header中添加Vary: Accept-Encoding,建议开启

gzip_vary on;

# 禁用IE 6 gzip

gzip_disable "MSIE [1-6]\.";

7、服务器缓存

location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {

access_log off;

expires 30d;

}

location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {

access_log off;

expires 24h;

}

location ~* ^.+\.(html|htm)$ {

expires 1h;

}

8、遍历数组往每一项中添加一个字段

this.lists = res.body.map(item => {

this.$set(item, 'type', -1)

return item

})

1、vue-router路由懒加载(按需加载页面,提高页面加载性能,提高用户体验)

export default new Router({

mode: 'history',

routes: [

{

path: '/',

component: resolve => require(['@/components/DefaultIndex'],resolve),

children: [

{

path: '',

component: resolve => require(['@/components/Index'],resolve)

},

{

path: '*',

redirect: '/Index'

}

]

})

2、webpack压缩图片(减少图片大小)

安装image-webpack-loader

npm install image-webpack-loader --save-dev

配置

在webpack.base.conf.js文件中引入配置

1: 引入:

require("image-webpack-loader")

2:配置:

module: {

rules: [

...(config.dev.useEslint ? [createLintingRule()] : []),

{

test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

loader: 'url-loader',

options: {

loader: 'image-webpack-loader',

options: {

bypassOnDebug: true,

}

}

},

或者也可配置为:

{

test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

use:[

{

loader: 'url-loader',

options: {

limit: 10000,

name: utils.assetsPath('img/[name].[hash:7].[ext]')

}

},

{

loader: 'image-webpack-loader',

options: {

bypassOnDebug: true,

}

}

]

}

3、取消额外打包的js文件

配置

在config/index.js文件里面修改

build:{}里面的productionSourceMap为false

4、打包后的js过大,将js打包多个文件

entry:{

main:'xxx.js'

}

plugins:{

new commonsChunkPlugin({

name:'commons',

minChunks:function(module){

// 下边return参考的vue-cli配置

// any required modules inside node_modules are extracted to vendor

return (

module.resource &&

/\.js$/.test(module.resource) &&

module.resource.indexOf(

path.join(__dirname, '../node_modules')

) === 0

)

}

}) ,

// 以下才是关键

new commonsChunkPlugin({

name:'charts',

chunks:['commons']

minChunks:function(module){

return (

module.resource &&

/\.js$/.test(module.resource) &&

module.resource.indexOf(

path.join(__dirname, '../node_modules')

) === 0 && ['jquery.js', 'highcharts.js','echarts'].indexOf( module.resource.substr(module.resource.lastIndexOf('/')+1).toLowerCase() ) != -1

)

}

})

}

5、去掉不必要的插件

plugins: [//webpack.config.jsnew webpack.optimize.UglifyJsPlugin({ warnings: false,

compress: {

join_vars: true,

warnings: false,

},

toplevel: false,

ie8: false,

]

6、gzip压缩

# 开启gzip

gzip on;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩

gzip_min_length 1k;

# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明

gzip_comp_level 2;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。

gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

# 是否在http header中添加Vary: Accept-Encoding,建议开启

gzip_vary on;

# 禁用IE 6 gzip

gzip_disable "MSIE [1-6]\.";

7、服务器缓存

location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {

access_log off;

expires 30d;

}
location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {

access_log off;

expires 24h;

}
location ~* ^.+\.(html|htm)$ {

expires 1h;

}
8、遍历数组往每一项中添加一个字段

this.lists = res.body.map(item => {

this.$set(item, 'type', -1)

return item

})
最近发表
标签列表