资源来自:https://developer.aliyun.com/ask/289308?spm=a2c6h.13066354.0.0.767533b5ZcyIwH
vue-cli实际上已经很成熟了,目录除了脚手架默认的,
vue-cli详细教程:https://www.cnblogs.com/fengzhenxiong/p/10213198.html
1、一般会额外创建views,components,api,utils,stores等;
2、下载重要插件,比如axios,dayjs(moment太大),其他的会根据项目需求补充;
安装axios: https://www.jianshu.com/p/dacbefd62e29
安装dayjs: https://www.cnblogs.com/cjrfan/p/9154539.html
3、封装axios,统一api调用风格和基本配置;
4、如果有国际化需求,配置国际化; 配置国际化参考:https://blog.csdn.net/eieiei438/article/details/94735872
5、开发,测试和正式环境配置,一般不同环境API接口基础路径会不一样;
Vue使用了Mustache语法,即双大括号的语法。
模板引擎: 负责组装数据,以另外一种形式或外观展现数据。
优点:
可维护性(后期改起来方便);
可扩展性(想要增加功能,增加需求方便);
开发效率提高(程序逻辑组织更好,调试方便);
看起来舒服(不容易写错)
多语言适配(i18n)与使用哪种前端框架无关。
本质上是维护一个 map,然后通过一个中间层返回当前语种的显示内容。
这个 map 可以存储在 DB,通过 HTTP 接口获取;
也可以硬编码在 javascript 文件中,通过某个公共的 translate 方法获取;
当前语种可以由用户选择存储在本地;
也可以由 WebServer 通过判断客户端 IP 地址来识别使用哪种语种;
https://www.cnblogs.com/rogerwu/p/7744476.html
1、确定线上环境是否在根路径上,配置资源根目录,vue-cli2 和 vue-cli3 字段不一致(assetsPublicPath 和 publicPath ),如果项目是根路径上,用’/’,’./‘都行,如果是在’/hc’这个路径上,用’./’ 相对路径(需history模式),也可以用’/hc/’。 在’/hc’路径上,如果需要本地和线上保持一致,可以用环境做判断设置不同的publicPath值。
2、确定静态文件放置的位置。
①、如果放在public/static,不经过webpack打包, 放在public 又分使用绝对路径和相对路径。
②、如果放在assets, 经过webpack打包, 使用的是相对路径
3、路径是否是动态的,如果是动态,需要用require() 引入。
ssr,即单页面后台渲染 参考:https://zhuanlan.zhihu.com/p/22361137
vue-meta-info 与prerender-spa-plugin 预渲染
vue-meta-info 参考:https://blog.csdn.net/weixin_43753330/article/details/106419950
prerender-spa-plugin 参考:https://www.cnblogs.com/you-uncle/p/13037300.html
nuxt 参考:https://zh.nuxtjs.org/
phantomjs 参考:https://www.jianshu.com/p/8210a17bcdb8
不支持ie8及以下,部分兼容ie9 ,完全兼容10以上
是因为vue的响应式原理是基于es5的Object.defineProperty的,而这个方法不支持ie8及以下
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
vue1.0的数据绑定完全依赖于数据侦测,使用Object.defineProperty方法使数据去通知相应watch,改变dom结构。vue2.0引入了虚拟dom,只通知到组件,提升了颗粒度。
1、使用v-for时记得加key,可以快速定位到需要更新的DOM节点,提高效率
2、永远不要把 v-if 和 v-for 同时用在同一个元素上。提高渲染效率
3、优先通过 Vuex 管理全局状态,而不是通过 this.$root
或一个全局事件总线
https://cn.vuejs.org/v2/style-guide/
设置comments属性,官网默认为舍弃注释 ...
在 index.html 中添加
在Vue-cli3可以修改vue.config.js的baseurl设定
ES6的转码。IE的兼容
Babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,
以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。 举例来说,ES6在Array对象上新增了Array.from
方法。Babel就不会转码这个方法。
如果想让这个方法运行,必须使用babel-polyfill,为当前环境提供一个垫片。
Babel默认不转码的API非常多,详细清单可以查看babel-plugin-transform-runtime模块的definitions.js文件。
https://www.cnblogs.com/princesong/p/6728250.html
都不是必须的
如果是普通组件那么只能是一个静态html
如果是函数式组件, 那么可以直接使用props等函数式组件属性
全部存在vue风格指南里面了
https://cn.vuejs.org/v2/style-guide/
1.检查nginx配置,是否正确设置了资源映射条件;
2.检查vue.config.js中是否配置了publicPath,若有则检查是否和项目资源文件在服务器摆放位置一致。
webpack:output.path
vue-cli3: outputDir
vue.config.js中设置outputDir
1.如果需要响应式,考虑使用虚表(只渲染要显示的数据);https://blog.csdn.net/achao_2020/article/details/107607510
2.如果不考虑响应式,变量在beforeCreated或created中声明(Object.freeze会导致列表无法增加数据)
配置ts-loader,tsconfig https://blog.csdn.net/u012987546/article/details/96482774
增加类型扩展,让ts识别vue文件 vue文件中script里面换成ts写法,
需要增加几个ts扩展的package, 比如vue-property-decorator
TypeScript 安装 https://www.runoob.com/typescript/ts-install.html
异步路由 ,异步加载
https://www.jianshu.com/p/dca3e41753ab
分屏加载
https://blog.csdn.net/leo187/article/details/79120774
按需加载
https://segmentfault.com/a/1190000011519350 https://github.com/cag2050/vue_product/blob/master/src/router/index.js
延时加载图片
https://blog.csdn.net/memejie/article/details/80839089
cdn, 域名拆分
http://www.baiwanzhan.com/site/t121469/
ssr直出
https://zhuanlan.zhihu.com/p/93199714
webpack压缩HTML/CSS/JS
首屏css单独提取内联
https://blog.csdn.net/qq_15009739/article/details/104605179
关键资源Proload
https://www.cnblogs.com/xiaohuochai/p/9183874.html
图片:不缩放,使用webp、小图片base64,iconfont,
webp https://www.zhihu.com/question/27201061
gzip
https://baike.baidu.com/item/gzip/4487553?fr=aladdin
dns-prefetch
https://blog.csdn.net/qq_35432904/article/details/83988726
静态资源单独域名,去掉cookie
https://blog.csdn.net/scorpio3k/article/details/53020270
默认的一个html文件,然后是
js,
css
vendor.js,
app.js,
app.css
错误:
1.打包后文件引用路径不对,导致找不到文件报错白屏
2.路由模式mode设置影响
优化:加载 js 太慢了,打包需要优化下,另外用 cdn 加快请求;图片等资源进行压缩处理;用服务端渲染。
router 是不是hash
是否需要配置nginx , publicPath ,
是不是要配置cdn
views目录存放一级路由的组件,即视图组件
components目录存放组件
store存放vuex相关文件
router目录存放路由相关文件
untils目录存放工具js文件
api目录存放封装好的与后端交互的逻辑
assets存放静态文件
Vue 代码层面的优化;
v-if 和 v-show 区分使用场景
computed 和 watch 区分使用场景
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
长列表性能优化
事件的销毁
图片资源懒加载
路由懒加载
第三方插件的按需引入
webpack 配置层面的优化;
Webpack 对图片进行压缩
减少 ES6 转为 ES5 的冗余代码
提取公共代码
模板预编译
提取组件的 CSS
优化 SourceMap 构建结果输出分析 Vue 项目的编译优化
基础的 Web 技术层面的优化:
开启 gzip 压缩
浏览器缓存
CDN 的使用
使用 Chrome Performance 查找性能瓶颈
1、在webpack.base.conf.js新增externals配置,表示不需要打包的文件,然后在index.html中通过CDN引入
externals: {
“vue”: “Vue”,
“vue-router”: “VueRouter”,
“vuex”: “Vuex”,
“element-ui”: “ELEMENT”,
“BMap”: “BMap”
}
2、使用路由懒加载
https://sass.bootcss.com/install
在request.js中对 axios 请求和响应进行劫持,统一处理,然后在 api 文件夹中引入 request.js 后再使用 封装后的方法进行请求
两部分 一部分 数据->虚拟dom->dom,
另一部分 响应式数据
这两部分大大节省了开发者对数据变动转换到页面显示的操作,可以让开发者聚焦业务,聚焦数据的处理。
多个实例引用了相同或相似的方法或属性等,可将这些重复的内容抽取出来作为mixins的js,export出去,在需要引用的vue文件通过mixins属性注入,与当前实例的其他内容进行merge。
mixins 就是混入。
一个混入对象可以包含任意组件选项。同一个生命周期,混入对象会比组件的先执行。
delete:只是被删除数组成员变为 empty / undefined,其他元素键值不变 (不能触发vue的响应式更新)
Vue.delete:直接删了数组成员,并改变了数组的键值(对象是响应式的,确保删除能触发更新视图,这个方法主要用于避开 Vue 不能检测到属性被删除的限制)(触发vue的响应式更新)
根据官方文档定义:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。
Vue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上。
vue.$set()
从详情页返回列表页时, 要保存所有状态, 比如: 滚动条位置, 数据, 下拉数据等
当时想用keep-alive, 后来没用, 直接存储一些关键数据, 返回到router时重新加载了数据
数据量大的表格很卡顿,Object.freeze() 解决
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
填写表单有些需要v-if来判断显示某种输入框时会有dom缓存,需要加唯一的key来标识
优点:
1、数据驱动视图,对真实dom进行抽象出virtual dom(本质就是一个js对象),并配合diff算法、响应式和观察者、异步队列等手段以最小代价更新dom,渲染页面
2、组件化,组件用单文件的形式进行代码的组织编写,使得我们可以在一个文件里编写html\css(scoped属性配置css隔离)\js 并且配合vue-loader之后,支持更强大的预处理器等功能
3、强大且丰富的API提供一系列的api能满足业务开发中各类需求
4、由于采用虚拟dom,让vue ssr先天就足
5、生命周期钩子函数,选项式的代码组织方式,写熟了还是蛮顺畅的,但仍然有优化空间(vue3 composition-api)
6、生态好,社区活跃
缺点:
1、由于底层基于Object.defineProperty实现响应式,而这个api本身不支持IE8及以下浏览器
2、csr的先天不足,首屏性能问题(白屏)
3、由于百度等搜索引擎爬虫无法爬取js中的内容,故spa先天就对seo优化心有余力不足(谷歌的puppeteer就挺牛逼的,实现预渲染底层也是用到了这个工具)
(1) vue是一套用于构建用户界面的渐进式框架,vue的核心库只关注视图层,我们使用vue时完全可以像跟使用jq一样,通过导入即可使用,当我们的页面足够多时,可以逐步的引入vue-router;当我们需要全局状态管理时,也可以再引入vuex;当我们需要构建一个大型的SPA项目时,完全可以使用工具vue-cli来构建。vue的渐进式表现在刚开始不会一股脑的把一些概念全抛给你,而是让你根据自己的需求来不断扩充。
(2) 官方对vue的评价是易用性、灵活性和高效性,我就这几点说一下自己看法:
① 易用性:vue提供数据响应式、基于配置的组件系统以及大量的指令等,这些让开发者只需关心核心业务即可。
② 灵活性:如果我们的应用足够小,可以只使用vue的核心库即可;随着应用的规模不断扩大,可以根据需求引入vue-router、vuex、vue-cli等其他工具。
③ 高效性:vue操作的是虚拟DOM,采用diff算法更新DOM,比传统的DOM操作更加的高效。
(3) 缺点:
① 不支持 IE8 及以下版本
② 这不是单纯的vue的缺点,其他框架如react、angular均有,那就是不利于SEO,不适合做需要浏览器抓取信息的电商网站,比较适合做后台管理系统。当然vue也有相关的SSR服务端渲染方式,也有针对vue服务端渲染的库,nuxt.js来提高SEO。
让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。 返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新;也可以作为最小化的跨组件状态存储器。
https://segmentfault.com/a/1190000019292569?utm_source=tag-newest
组件递归:组件之间相互引用,A用B,B又用了A
在errorCaptured中更改组件状态,触发更新后再次报错(未设置短路条件),陷入无限循环
访问根实例、访问父组件、子组件
在updated钩子中改data的属性值,然后又触发更新,导致无限循环
分为errorCaptured和errorHandler
errorCaptured是组件内部钩子,可捕捉本组件和子孙组件抛出的错误,接收error, vm, info三个参数,return false后可以阻止错误继续向上抛出
errorHandler为全局钩子,使用Vue.config.errorHandler配置,接收参数与errorCaptured一致,2.6后可捕捉v-on与promise链的错误,可用于统一错误处理与错误兜底。
建议在created里注册,在beforeDestory移出;在组件内的beforeRouteLeave中移除事件监听
jsBridge,建立连接,然后相互调用
用WebViewJavascriptBridge
export const connectWebViewJavascriptBridge = callback => { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( ‘WebViewJavascriptBridgeReady’, function() { callback(WebViewJavascriptBridge) }, false ) } }
我的做法就是让app在webview把app的方法暴露在window上让前端调用、反之app调用前端的方法也需要前端把方法暴露在window上(window.xxx = 方法或值 ),页面销毁的时候移除方法(delete window.xxx)
{{list[choose].content}}
Object.defineProperty定义新属性或修改原有的属性;
vue的数据双向绑定的原理就是用的Object.defineProperty这个方法,里面定义了setter和getter方法,通过观察者模式(发布订阅模式)来监听数据的变化,从而做相应的逻辑处理。
vue 的data避免使用箭头函数
vue中methods中函数尽量不要使用箭头函数,会改变this指向,在vue-cli构建的项目中this会为undefined
要做实例中增加delimiters 2.0后只能在实例中修改了,1.0还可以全局修改
new Vue({ delimiters: ['${', '}'] })
// 分隔符变成了 ES6 模板字符串的风格
计算出虚拟 DOM 中真正变化的部分,并且只针对该部分进行 DOM 更新,而非重新渲染整个页面
vNode oldNode
https://www.cnblogs.com/wind-lanyan/p/9061684.html
@click="func"
默认第一个参数传入event对象 @click="func(0, $event)"
如果自己需要传入参数和event对象,则需要使用$event
来获取event对象并传入func
单向数据流:所有状态的改变可记录、可跟踪,源头易追溯;所有数据只有一份,组件数据只有唯一的入口和出口,使得程序更直观更容易理解,
有利于应用的可维护性;一旦数据变化,就去更新页面(data-页面),但是没有(页面-data);如果用户在页面上做了变动,那么就手动收集起来(双向是自动),合并到原有的数据中。
双向数据流:无论数据改变,或是用户操作,都能带来互相的变动,自动更新。
举例就是:父传子的props就是单向数据流,v-model就是双向数据流
vant https://www.w3cschool.cn/vantlesson/
mint http://mint-ui.github.io/#!/en
vant中使用better-scroll无法滚动的问题
路由跳转时van-field的样式变成左右对半分,lable-width不生效,需要刷新才行
用法:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
DOM的更新是异步执行的,只要数据发生变化,将会开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。
简单来说,就是当数据发生变化时,视图不会立即更新,而是等到同一事件循环中所有数据变化完成之后,再统一更新视图。
关于异步的解析,可以查看阮一峰老师的这篇文章,具体来说,异步执行的运行机制如下。
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
例子:
//改变数据
vm.message = 'changed'
//想要立即使用更新后的DOM。这样不行,因为设置message后DOM还没有更新
console.log(vm.$el.textContent) // 并不会得到'changed'
//这样可以,nextTick里面的代码会在DOM更新后执行
Vue.nextTick(function(){
console.log(vm.$el.textContent) //可以得到'changed'
})
vue的数据劫持有两个缺点:
1、无法监听通过索引修改数组的值的变化
2、无法监听object也就是对象的值的变化
所以vue2.x中才会有$set属性的存在
proxy是es6中推出的新api,可以弥补以上两个缺点,所以vue3.x版本用proxy替换object.defineproperty
全局的theme属性然后做class判断或者加载不同的样式文件。一种是编译时换肤 一种是用户操作换肤。编译时换肤可以通过css in js相关技术修改css预处理器的变量 。用户操作换肤 只能内置一些styleb变量供用户选择了
https://echarts.apache.org/en/index.html
在切换tab时 第二个tab的图表无法正常显示 切换tab时使用方法@tab-click="handleClick"加载图表的render函数
tab切换时地图显示不正常,需要在 el-tab-pane 中添加 :lazy="true"属性
1.使用vue的transition标签结合css样式完成动画
2.利用animate.css结合transition实现动画
animate.css https://www.dowebok.com/demo/2014/98/
3.利用 vue中的钩子函数实现动画
1、document.getElementById("id")
2、this.$refs.xx
还有一些特殊的,比如this.$root、this.$parent、this.$children
https://github.com/Myh-cs/todolist-vue
https://vue-test-utils.vuejs.org/zh/
给 process.env 对象添加了一个属性 npm_config_report: “true”,表示开启编译完成后的报告
devServer中把所有的服务人员的地址代理都写进去,
然后动态更改接口的baseUrl,这样切换不同后端人员的时候不用重启
通过获取当前用户的权限去比对路由表,生成当前用户具的权限可访问的路由表,通过 router.addRoutes 动态挂载到 router 上。
如果权限角色是动态的,那么要为每个按钮做标识,根据这个标识去查哪些角色拥有该权限,再根据登录人的权限角色进行显示与否。
Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API;vue是单页面应用,使页面局部刷新,
不用每次跳转页面都要请求所有数据和dom,这样大大加快了访问速度和提升用户体验。而且他的第三方ui库很多节省开发时间。
Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件。
特性:
允许为 Vue 组件的每个部分使用其它的 webpack loader,例如在 的部分使用 Sass 和在
的部分使用 Pug;
允许在一个 .vue 文件中使用自定义块,并对其运用自定义的 loader 链;
使用 webpack loader 将 和
中引用的资源当作模块依赖来处理;
为每个组件模拟出 scoped CSS;
在开发过程中使用热重载来保持状态。
https://github.com/vuejs/vue-loader/tree/v16.0.0-rc.1
extend的作用是继承当前的Vue类,传入一个extendOption生成一个新的构造函数。在extend的时候会进行mergeOption,
融合Vue原型上的baseOption,所以extend出来的子类也能使用v-model、keep-alive等全局性的组件。
作用是生成组件类。在挂载全局组件和设置了components属性的时候会使用到。在生成DOM的时候会new 实例化挂载。
使用extend时,data选项必须是函数
虚拟DOM本身是一个JavaScript对象模拟真实DOM ,用对象的属性去描述一个DOM节点,最终也只是一个真实DOM的映射
1.监听地址栏中hash变化驱动界面变化
2.用pushsate记录浏览器的历史,驱动界面发送变化
3.直接在界面用普通事件驱动界面变化
它们都是遵循同一种原则:div 的显示与隐藏
https://www.cnblogs.com/fanfan-90/p/12744599.html
介绍:SPA应用就是一个web应用,可理解为:是一种只需要将单个页面加载到服务器之中的web应用程序。当浏览器向服务器发出第一个请求时,服务器会返回一个index.html文件,它所需的js,css等会在显示时统一加载,部分页面需要时加载。
优点:
1.良好的交互式体验。意思是:用户无需刷新页面,获取数据通过异步ajax获取,页面显示流畅
2.良好的前后端分离模式(MVVM),减轻服务端压力。服务器只需要输出数据就可以,不用管逻辑和页面展示,吞吐能力会提高几倍
3.共用同一套后端程序代码,不用修改就可用于web界面,手机和平板等客户端设备
缺点:
1.不利于SEO优化
2.由于单页应用在一个页面中显示,所以不可以使用浏览器自带的前进后退功能,想要实现页面切换需要自己进行管理
3.首屏加载过慢(初次加载耗时多),原因是:为了实现单页web应用功能及展示效果,在页面初始化的时候就会将js,css等统一加载,部分页面在需要时加载。当然也有解决方法。
解决方法:①使用路由懒加载 ②开启Gzip压缩 ③使用webpack的externals属性把不需要的库文件分离出去,减少打包后文件的大小 ④使用vue的服务端渲染(SSR)
举例spa应用:网易云音乐、QQ音乐等
1、绝对路径直接引入
在index.html中用script引入
然后在webpack中配置external
externals: { ‘jquery’: ‘jQuery’ }
在组件中使用时import
import $ from ‘jquery’
2 、在webpack中配置alias
resolve: { extensions: ['.js', '.vue', '.json'], alias: { '@': resolve('src'), 'jquery': resolve('static/jquery-1.12.4.js') } }
然后在组件中import
3、在webpack中配置plugins
plugins: [ new webpack.ProvidePlugin({ $: 'jquery' }) ]
全局使用,但在使用eslint情况下会报错,需要在使用了 $ 的代码前添加 /* eslint-disable*/ 来去掉 ESLint 的检查。
全局过滤器
Vue.filter(
'addHobby',(val,hobby)=>{
return val + hobby
}
)
局部过滤器
filters:{
addHobby(val,hobby){
return val + hobby
}
}
template也会翻译成render,只有一点,template中元素的tag_name是静态的,不可变化,使用createEelment可以生成不同tag_name, 比如h1 … h6, 可以通过一个number变量控制
也是组件传值的一种方式(例如兄弟组件)
通过Bus.$emit('on-message',this.abc)
的方式进行发布消息,
它有两个参数,一个是消息声明,第二个是传递的值,key和value的关系
另一个组件接收通过Bus.$on('on-message', msg => { })
的方式,第一个参数是传递过来的消息声明,第二个参数可以是个函数,msg就是做为传递过来的参数
组件化开发 复用性 先转化为AST树,在得到的render函数中返回VNode(vue的虚拟DOM节点)
el: 把当前实例挂载在元素上
template: 实例模版, 可以是.vue中的template, 也可以是template选项, 最终会编译成render函数
render: 不需要通过编译的可执行函数
template和render, 开发时各有优缺点, 不过在线上尽量不要有template
render, 没有则去编译
编译vdom
对实例进行watch