20170709 - 20171128:《imooc-vue.js高仿饿了么》 |
1、第一章 课程简介
1-1课程简介
一、需求分析—脚手架工具—数据mock—架构设计—代码编写—自测—编译打包。
二、功能技术分析
2.1后端 vue-resource
2.2 前端 vue-router
2.3 第三方js库 better-scroll
最大程度组件化
三、前置基础
3.1 html、css、js、es6
1-2课程安排
一、组件化、模块化的开发方式,提升效率。
二、学习内容:
vue-resource ajax通讯
webpack 构建工具
es6+eslint eslint:es6代码风格检查工具
工程化、组件化、模块化
移动端经常使用开发技巧:flex弹性布局、css stickyfooter布局
酷炫的交互设计
第二章、vue.js介绍
2-1 vuejs介绍-近年来前端开发趋势
一、ie6-ie8:不支持es5
二、架构从传统后台mvc向rest api+ 前端mv迁移
三、mv包括:mvc, mvp, mvvm
vuejs介绍-mvvm
一、view(视图-dom)—viewmodel(通信-观察者)—model(数据-javascript对象)
二、应用场景
2.1 针对具备复杂交互逻辑的前端应用
2.2提供基础的架构抽象
2.3 经过ajax数据持久化,保证前端用户体验
三、mvvm框架:angularjs, reactjs, vuejs
2-3 vuejs介绍-什么是vuejs及vuejs生态
一、vuejs是数据驱动+组件化的前端开发
2-4 vuejs介绍-对比angular, react
一、vue.js更轻量,gzip后大小20k+,angularjs,56k
二、vuejs更易上手,学习曲线平稳。
三、吸收两家之长,借鉴了angular的指令和react的组件化。
2-5 vuejs介绍-vuejs核心思想
一、数据驱动:dom是数据的一种天然映射
二、组件设计原则
2.1页面上每一个独立的可视/可交互区域视为一个组件。
2.2每一个组件对应一个工程目录,组件所须要的各类资源在这个目录下就近维护
2.3页面不过是组件的容器,组件能够嵌套自由组合。
第三章 vue-cli开启vuejs项目
3-1 vue-cli介绍
一、vue-cli是vue的脚手架工具。
脚手架-帮助咱们写好基础的代码。
vue-cli能够帮咱们搞定:目录结构,本地调试,代码部署,热加载,单元测试。
二、vue-cli是一个node包
3-2 vue-cli安装
一、项目安装
(1)$ node -v :查node版本,要升级到4以上
(2)cd /Users/yquanmei/ee/git/imooc-vue-eleme
(3)$ sudo npm install -g vue-cli
(4)$ vue
(5)$ vue init webpack eleme-project
二、?Setup unit tests with Karma + Mocha? n 是否模块化单元测试
(2)?Setup e2e tests with Nightwatch? (Y/n) n
三、
cd … :返回上一级文件目录
ls:(list)列出当前目录全部文件
ll -a 项目全部目录
四、$ sudo npm install
五、总结:安装vue
(1) cd /Users/yquanmei/ee/git/imooc-vue-eleme
(2) $ sudo npm install -g vue-cli
(3) $ vue init webpack eleme-project
(4) cd eleme-project
(5) $ sudo npm install
(6) $ npm run dev
3-3 项目文件介绍
3.3.1 (1)build、config目录:webpack配置相关。
(2)node_modules 文件:npm install安装的依赖代码库。
(3)src:开发源代码。
(4)static:静态资源
(5).babelrc:babel相关配置。
3.3.2
一、presets:预设。
二、editorconfig:编辑器的配置
三、eslintignore:忽略语法检查的目录文件
四、eslintrc.js:eslint的配置文件
(1)‘arrow-parens’: 0, // 箭头函数用小括号括起来
若是某个规则不想要的时候,就用0
五、当前环境若是是开发环境,容许debugger;若是是生产环境,不容许debugger;javascript
'no-debugger':process.env.NODE_EVN==='production':2?0
3-4项目运行
一、webstorm不支持es6语法时,配置:properties-languages & frameworks-javascript-ecmascript6
二、自动格式化:mac:command+option+L
windows:control+alt+L
3-5 webpack打包(上)
一、path:提供一些文件路径操做方法,
二、express:node的一个框架
三、webpack:核心编译工具。
四、merge:合并编译文件用的。
3-6webpack打包(中)
一、extensions:[’’,’.js’,’.vue’],自动补全文件后缀。
二、new webpack.optimize.OccurenceOrderPlugin()
:webpack优化插件
三、new HtmlWebpackPlugin:filename:生成的文件名
四、output的publicPath:请求的静态资源绝对路径。
3-7webpack打包(下)
一、devMiddleware:打包后的文件都放在内存中。
第4章 项目实战-准备工做
4-1需求分析
一、spa单页应用,切换子页面时不会去刷新整个页面
4-2项目资源准备
一、webpack的url-loader会帮咱们作图片打包,先base64,再打包
4-3 图标字体制做
一、icomoon字体图标制做
https://icomoom.io
1.1 svg图标导入
4-5 mock 数据(模拟后台数据)
一、build里的dev-server.js是webpack打包入口。
二、google里的json-view插件可让json数据在浏览器中的显示更直观。
三、express起一个server。
四、全部与api相关的,都会经过api这个路由。
第5章 项目实战-页面组件开发
5-1组件拆分(上)
一、三个区块的切换用vue-router来实现。
二、报错:错误:extra semicolon,有多余的分号,由于默认eslint配置的时候,是配置不能有分号,因此在js语句后面添加分号会报错。
解决方法:。eslintrc.js- rules,'semi':['error','always']
:必定要写分号。
三、/* eslint-disable no-new */
main.js中加入这行代码,能够不将new的东西赋值给一个变量。
5-2组件拆分(中)
5-3组件拆分(下)
一、错误:[vue warn]:do not user built-in or reserved HTML elments as component id: header
不要用原生的html标签header
二、终端打开和关闭tomcat
(1)终端打开tomcatcss
cd /usr/local/apache-tomcat-8.5.13/bin sudo chmod 755 /usr/local/apache-tomcat-8.5.13/bin/*.sh sudo sh startup.sh
(2)终端关闭tomcathtml
cd /usr/local/apache-tomcat-8.5.13/bin sudo chmod 755 /usr/local/apache-tomcat-8.5.13/bin/*.sh sudo sh shutdown.sh
三、iphone6设计稿:物理像素750, dpi=2
四、终止一个错误的命令:control + c
五、stylus-loader安装:(1)package.json中加入:“stylus-loader”: “^2.1.1”,.(2)sudo npm install
五、stylus-loader安装时出现错误:
(1)npm WARN stylus-loader@2.5.1 requires a peer of stylus@>=0.52.4 but none was installed.
解决方法:①把stylus-loader 改为 “^2.4.0” 好比: “stylus-loader”: “^2.4.0”, 若是没有这条记录就自行添加一条。②须要多添加一条插件 “stylus”: “0.52.4” 在package.json里面增长就好 而后执行安装命令 便可解决
(2)npm WARN deprecated minimatch@0.3.0: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
解决方法:①npm update minimatch@3.0.2 ②npm update -d
六、postcss插件能够搞定css兼容问题。
5-4 vue-router(上)
一、1.0 -->2.0
https://router.vuejs.org/en/essentials/getting-started.html
https://router.vuejs.org/zh-cn/essentials/getting-started.html
5-5 vue-router (下)
一、1px:伪类+缩放。前端
border-1px($color) position:relative &:after display:block position:absolute left:0 bottom:0 width:100% border-top:1px solid $color content:" " border-none() &:after display:none @media (-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5) .border-1px &::after -webkit-transform:scaleY(0.7) transform:scaleY(0.7) @media (-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2) .border-1px &::after -webkit-transform:scaleY(0.5) transform:scaleY(0.5)
第6章 项目实战-header组件开发
6-1 vue-resource应用(上)
一、安装vue-resource
(1)pakage.json里添加vue-resource.
(2)sudo npm install
二、每一个实例,实例化以后都会有一个生命周期。
6-3 外部组件(1)
一、avatar:['ævətɑː],头像。
二、vue里不能直接用src,要用v-bind,就是:src
6-5 外部组件(3)
一、css影响宽高的写在前面,影响样式的写在后面。
6-9 详情弹层页(1)-实现弹出层
一、css sticky footers布局:若是内容不够长,会固定在底部,若是内容够长,会被顶下去。
相关文章:http://www.w3cplus.com/css3/css-secrets/sticky-footers.html
二、vue的data()是一个function
6-14 详情弹层页(4)-小标题自适应经典flex布局实现
一、
vue
<div class="title"> <div class="line"></div> <div class="text"></div> <div class="line"></div> </div>
若是用span,样式会出现一些问题。
第7章 项目实战-goods商品列表页开发
7-2 左侧布局
一、能用class 的时候,就不要用标签写样式,若是是多层级的标签嵌套,容易形成运行缓慢。
7-6 better-scroll运用(1)
一、
vue1.0的v-el:foods-wrapper
改为vue2.0以后,再也不是羊肉串形式,而是驼峰的形式。java
ref="foodsWrapper"
7-7 better-scroll运用(2)
一、class="food-list-hook"
hook 通常表示这个样式是被js用来选择,而没有实际的样式。
二、若是要跟踪一个变量,就放到data里。
三、probeType: 3。实时告诉咱们滚动的位置,至关于探针的做用。
7-8 better-scroll运用(3)
一、event._constructed在js原生中是为false,betterscroll派发的click中为true。vue有_constructed属性,原生的js中没有。
判断这个属性是由于,在电脑端,click事件会执行2次,一次是本来的click,另外一次是派发的click。而在手机端只会执行一次click,即执行派发的那次,而默认的click会被阻止掉。node
if (!event._construsted) { return; }
这段代码是将电脑端默认的click事件也阻止,这样手机,电脑端行为就一致了,都只执行一次click事件。
注:实际不可行,改成:react
if (event) event.prenventDefault();
二、引入的库和原生js库:
ref访问到dom对象,refs.getElementsByClassName()至关于拿到一个原生dom。
$nextTick():要计算有关dom相关时的操做,要保证dom已经渲染了。dom真正发生变化是在$nextTick()以后。
7-12 shopcart购物车组件(4)
一、seller的传递
(1)app.vuewebpack
<router-view :seller="seller"></router-view>
(2)goods.vueios
<shopcart :delivery-price="seller.deliveryPrice"></shopcart>
props: { seller: { type: Object } },
(3)shopcart.vue
{{deliveryPrice}}
二、vue里若是是array或者object,default(){}是做为函数。
三、插值是{{}}
7-16 cartcon control组件(2)
一、新增和删除某个字段的时候,若是要观察这个字段,须要用vue的接口,
Vue.set(this.food, 'count', 1);
7-17 cartcon control组件(3)
一、transform translate3D(0,0,0)能够开启一个硬件加速,让动画更流畅一些。
7-19 购物车小球动画实现(2)
一、动画效果:
.move-enter-active,.move-leave-active .move-enter,.move-leave-active
7-24 购物车详情页(4)
一、vue的阻止冒泡:@click.stop.prevent=
二、动画展开过程实现较好,可是在隐藏的过程当中,会直接过渡到display:none,从而没有实现动画效果。(aSuncat:由于样式使用错了,应该要用&.fold-leave-active,而不是&.fold-leave)
三、ios的模糊效果:backdrop-filter:blur(10px)
一、报错:'food' is defined but never used
,缘由:未在components中注册food
一、父组件能调用子组件的方法,子组件不能调用父组件的方法。
二、若是是外部能够调用的方法,直接写show(),若是是内部私有的方法,通常前面下_,写_show()
;
一、padding-top设置为100%时,是相对于盒子的宽度来计算的。
二、图片宽度,高度设置,动态加载的图片
设置padding-top:100%
.image-header position:relative width:100% height:0 padding-top:100% img position:absolute top:0 left:0 width:100% height:100%
一、props的数组的对象都要返回一个函数。
一、每次show()的时候数据初始化,由于是不一样商品页面跳进来的,每次都须要进行初始化。
一、在vuejs2.0中,任何试图在组件内修改经过props传入的父组件数据都被认为是anti-pattern的,报如下错误:
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders
解决:经过$emit一个事件通知该数据的源头组件来更新web app的数据;
二、aSuncat:双向数据绑定的时候,“只看内容的评价”事件没有绑定成功,到时候再回来看看(vue2.0)(aSuncat备注:见第13章,vue1.0到vue2.0的升级,子组件向父组件传输数据。)
一、给ratingSelect组件传入的selectType和onlyContent都是基础类型,在组件内部修改这些基础属性,是不会影响父层的selectType和onlyContent
一、export function的时候在引入的过程加{}。
二、日期格式化:| formatDate
一、vue的声明周期,执行到created的时候,不能保证dom是已经被渲染的。ready则是都渲染了的。
一、“评论”切换到“商家”时,不会执行watch方法,watch方法只在页面刷新的那次执行。
一、报错:Error in callback for watcher “seller”: “TypeError: Cannot read property ‘style’ of undefined”。
(aSuncat:不知道错在哪里,外层的滚动也没有实现效果,可是没有报错。后来改了子组件向父组件传值的方法就行了,但滚动仍是没有实现)
一、收藏的前端缓存:localStorage()
二、[^?&]
:非问号或&
三、给对象扩展属性的方法:
Object.assign()接收3个参数。
this.seller = Object.assign({}, this.seller, response.data);
四、获取url中指定属性的值
/** *解析url参数 * @example ?id=123456&a=b * @return Object {id:12345,a:b} */ export function urlParse() { let url = window.location.search; let obj = {}; let reg = /[?&][^?&]+=[^?&]+/g; let arr = url.match(reg); // 返回一个数组 // ['?id=12345', '&a=b'] if (arr) { arr.forEach((item) => { let tempArr = item.substring(1).split('='); let key = decodeURIComponent(tempArr[0]); let val = decodeURIComponent(tempArr[1]); obj[key] = val; }); } return obj; };
一、
export function saveToLocal(id, key, value) { let seller = localStorage.__seller__; if (!seller) { // 历来没有建立__seller__ seller = {}; seller[id] = {}; } else { seller = JSON.parse(seller); if (!seller[id]) { // 没有建立这个id对应的存储 seller[id] = {}; } } seller[id][key] = value; localStorage.__seller__ = JSON.stringify(seller); }; export function loadFromLocal(id, key, def) { let seller = localStorage.__seller__; if (!seller) { return def; } seller = JSON.parse(seller)[id]; if (!seller) { return def; } let ret = seller[key]; return ret || def; };
一、从点“商品”到点“评论”,dom会从新渲染,vue的生命周期从新执行,因此页面会闪一下。
二、但愿切换组件时,组件状态保留:
router-view添加属性keep-alive , 组件状态缓存到内存。
<router-view :seller="seller" keep-alive></router-view>
一、npm run build
二、build=webpack.prod.conf.js
ExtractTextPlugin:webpack提供的插件,将编译过程当中的css独立提取出来,而不是打包到Js中.
三、UglifyJsPlugin:压缩js代码
ExtractTextPlugin:
minify:压缩html
CommonChunkPlugin:将一些第三方库打包到vendor中。
四、cp: static目录下的文件拷贝到dist
一、不能启动静态server,由于有些后端api接口,用express启动小型server。
二、config——index.js
(1)productionSourceMap: 是否启用调试,生产环境下为false
(2)设置完成之后:①npm run build . ② node prod.server.js。sources中就不会出现可调试的代码,不会出现webpack://一项。
一、cmd返回上一级文件:cd ..
二、参考资料
(1)Vue.js官网(https://vuejs.org.cn/)
(2)vue-cli(https://github.com/vuejs/vue-cli)
(3)vue-resource(https://github.com/vuejs/vue-resource),非vue官方出的ajax请求的库.
(4)vue-router(https://github.com/vuejs/vue-router)
(5)better-scroll(https://github.com/ustbhuangyi/better-scroll)
(6)webpack官网(https://webpack.github.io/)
(7)Stylus中文文档(http://www.zhangxinxu.com/jq/stylus)
(8)es6入门学习(http://es6.ruanyifeng.com)
(9)eslint(http://eslint.org/docs/rules),代码风格检查器
(10)设备像素比(http://www.zhangxinxu.com/wordpress/2012/08/windowdevicepixelratio/)
(11)flex布局(http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool)
(12)贝塞尔曲线测试(http://cubic-bezier.com/)
一、配置文件的修改:
(1)package.json 文件修改
(2)build目录修改
(3)config目录修改
一、vue-router api变化
(1)初始化路由变化
(2)v-link指令替换为<router-link>
组件
二、vue 2.0语法变化
(1)v-for指令的变化
(2)v-el、v-ref指令的变化
(3)模板变化,组件只容许一个根元素
(4)组件通讯变化 $dispatch废除
(5)事件监听变化,废除events属性
(6)不能在子组件直接修改父组件传入的prop
(3)过渡的变化,transition组件
(4)小球下落动画实现的变化
(5)keep-alive属性变为组件
三、子组件向父组件传值
ratingselect.vue
select(type, event) { if (event) event.preventDefault(); this.$emit('select', type); },
food.vue
<ratingselect @select="selectRating"></ratingselect> selectRating(type) { this.selectType = type; this.$nextTick(() => { this.scroll.refresh(); }); }
一、当只用Javascript过渡的时候,在enter和leave中,回调函数done是必须的。不然,它们会被同步调用,过渡会当即完成。
20171220(已看完):《imooc- vue 音乐app》 |
一、vue init webpack vue-music
二、
三、cd vue-music
四、npm install
五、npm run dev
一、package.json:
①devDependencies增长
"stylus":"^0.54.5", "stylus-loader":"^2.1.1"
二、.eslintrc.js:
①rules增长
'semi': ['error','always'], // 语块结尾要加分号 'eol-last': 0, 'space-before-function-paren': 0 //function左边是否要加空格
三、build 的webpack.base.conf.js
alias: { // '@': resolve('src') }
改为
alias: { 'src': resolve('src'), 'assets': resolve('src/assets') }
四、config里的index.js
autoOpenBrowser: false,
改为autoOpenBrowser: true,
// 自动打开浏览器显示页面
一、package.json
①
"dependencies": { "vue": "^2.5.2", "vue-router": "^3.0.1" }
改为
"dependencies": { "babel-runtime":"^6.0.0",// 对一些es6的语法进行转译 "vue": "^2.5.2", "vue-router": "^3.0.1", "fastclick":"^1.0.6" //解决移动端点击300毫秒延迟的问题 }
②devDependencies增长
“babel-preset-stage-2”: “^6.22.0”,的下面增长
"babel-register":"^6.22.0", "babel-polyfill":"^6.2.0", //补丁,es6的api进行一些转译,好比promise
二、main.js
①
import 'babel-polyfill'
要放在main.js的最上面,辅助es6编译过程当中的操做
②
import fastclick from './fastclick' fastclick.attach(document.body)
三、输入npm install,安装依赖。
@import “~assets/stylus/variable”。
assets前有~。
一、数据在network中的xhr中没有找到,说明不是经过ajax请求获取的数据, 在js中找后缀为.fcg的文件,js中有获取数据获得的文件。
一、jsonp原理。
二、jsonp发送的不是ajax请求,而是动态建立了一个script标签。
三、jsonp具体实现,手写jsonp。
四、要用的jsonp的库,webmodules/jsonp。地址: https://github.com/webmodules/jsonp
(1)package.json里的dependencies中加入"jsonp":"0.2.1"
,而后npm install.
alias/ˈeɪliəs/
一、浏览器的刷新一般是11毫秒一次。
一、host:c.y.qq.com, referer:https://y.qq.com/portal/playlist.html的限制致使500错误。
一、request-header,后端代理解决,发送http请求修改referer。
二、build-dev-server.js,
三、axios库,浏览器发送xhr请求,node发送http请求。
四、pakage.json的dependencies
增长"axios": "^0.17.1"
五、getDiscList做用:从真实的qq地址,经过axios发送http请求,把浏览器传过来的参数传给qq的服务端,而后把获得的数据传给浏览器端。
一、v-html="item.creator.name"
对html的字符进行转译。
一、<scroll class="recommend-content" :data="discList">
监听到data的变化,数据撑开dom,可以滚动,若是不加:data,是在mounted的时候初始化scroll,这个时候dom 的高度为0,不能滚动。
一、为使滚动更完美,能够监听img的onload事件
一、scroll要滚动必需要保证dom都是加载了的。
二、图片懒加载:vue第三方插件-vue-lazyload
三、slider点不动,fastclick,betterScroll,slider冲突了。解决:给img添加class:needsclick,fastclick若是监听到这个class,就不会阻止它的click行为。
一、数组按字母排序
ret.sort((a, b) => { return a.title.charCodeAt(0) - b.title.charCodeAt(0); });
一、listview中加入lazyload,<img class="avatar" v-lazy="item.avatar">
一、map() 方法返回一个由原数组中的每一个元素调用一个指定方法后的返回值组成的新数组。
参考连接:
https://www.cnblogs.com/leejersey/p/5462427.html
一、parseIn(),能将字符串转换为数字类型。
一、vuex
一、store文件夹中含有:
index.js // 入口 state.js // 状态管理 mutations.js mutations-types.js // 存储mutation相关的字符串常量 getters.js // 映射,用getter去取组件中的数据 actions.js // 异步操做,mutation封装
一、
if (!this.singer.id) { // 若是刷新当前页面,则返回歌手页面,再从新点击进歌手详情页面 this.$router.push('/singer'); return; }
一、设置成类
(1)能够将代码集中在一个地方去维护,不须要在不少地方写相同的代码。
(2)类的扩展性比对象强,是面向对象的编程方式。
二、工厂方法:不直接调用New,提供一个方法,返回一个实例。
一、相似于css,prefix对js进行封装,transform, webkitTransform.
一、动态建立css动画用到库:create-keyframe-animation
一、interval = interval | 0;
|0 就至关因而math.floor(),向下取整。
二、pad方法补0
_pad(num, n = 2) { let len = num.toString().length; while(len < n) { num = '0' + num; len++; } return num; }
一、<progress-circle radius="32" :percent="percent"></progress-circle
,若是传入的是固定的值,能够不用bind,便可以写radius="32"
,不用写:radius="32"
。不过由于须要的是数字32,radius="32"
传入的是字符串32,不符合要求,因此仍是要用:radius="32"
, 也能够用:radius="radius"
, 而后给radius赋值32。
一、修改播放模式mode时,实际上是在改变播放列表playlist
二、
将原有数组顺序打乱
function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } export function shuffle(arr) { for (let i = 0; i < arr.length; i++) { let js = getRandomInt(0, i); let t = arr[i]; arr[i] = arr[j]; arr[j] = t; } return arr; }
一、const rect = this.$refs.progressBar.getBoundingClientRect();
获取某个dom最左边的点的位置。能够经过rect.left获取到距离屏幕左边的距离。
二、let _arr = arr.slice();
, 拷贝了一个数组。
一、对base64字符串进行解码,用到一个库,js-base64。
二、let { musicData } = item;
至关因而
let musicData = item.musicData;
三、歌词解析第三方库:lyric-parser
一、Math.abs(deltaY)
对deltaY取绝对值
二、
if (!this.touch.initiated) { return; } const touch = e.touches[0]; const deltaX = touch.pageX - this.touch.startX;
一、微信中,微信后台运行时,js不执行,可是这首歌会播放完,这首歌播放完时,不会执行end,songReady就不会变成true。
解决:watch中currentSong中,使play方法延迟时间更长一点,因此用setTimeout,不用
一、若是多个组件都须要写一个逻辑的话,推荐用mixin:scroll过程当中,屏幕下方的mini播放器占高度,因此有歌曲须要滚动时,scroll的bottom要设置一下
二、import {playlistMixin} from 'common/js/mixin';
mixins: [playlistMixin],
hanlePlaylist(playlist) { const bottom = playlist.length > 0 ? '60px' : ''; this.$refs.list.$el.style.bottom = bottom; this.$refs.list.refresh(); },
三、handlePlaylist函数会报错Cannot read property 'refresh' of undefined
,scroll.vue的refresh函数中须要将this.refresh && this.scroll.refresh();
改为this.refresh && this.scroll && this.scroll.refresh();
,等this.scroll初始化完成,有值时才refresh。
一、input的v-model实现双向绑定.
一、
...obj // 对象扩展符
ret.push(...data.zhida, ...{type: TYPE_SINGER}); // 将type属性添加到data.zhida这个对象上去
二、concat()链接2个数组。
三、webpack_require_.i(…) is not a function,这个错误一般是import的值是有问题的。
一、filterSinger是有关song的内部函数(common/js/song.js里的),不适合暴露在外面,及不适合suggest.vue中去引用,suggest.vue中的数据经过createSong(common/js/song.js有关song的可供外部引用的函数)进行处理。
二、scroll组件的上拉刷新pullup
一、报错:do not mutate vuex store state outside mutation handlers(不要在Mutation回调函数以外修改state).
let playlist = state.playlist;若是修改playlist,会修改state的playlise;
解决方法:let playlist = state.playlist.slice(),为state的playlist建立副本,而后修改的是副本。
一、优化方面:
(1)搜索若是没有数据,给出相应提示。
(2)对Input输入进行节流操做,即不是每变化一个字符就进行一次请求。节约带宽,提升性能。
父组件能够调用子组件的方法。
this.$refs.searchBox.blur();
一、sessionStorage,和localStorage的库:good-storage
一、由于span是li的子元素,因此要用@click.stop,防止点击事件的冒泡。
二、删除历史:actions.js(cache.js,), search.vue。
三、mapActions的时候,会给vue实例添加一个deleteSearchHistory这个方法,能够直接使用(在search.vue中使用),派发出来的事件是个query(item),恰好deleteSearchHistory接收一个query。
四、若是mehod的内容和mapActions的方法同样内容,就能够直接用mapActions里的方法名
一、基础组件一般不会放有关vuex的内容。通常都是data,props,methods,event这些东西。
一、scroll组件里只能有一个元素,否则只有第一个元素会生效,根据第一个元素的高度,来计算是否须要滚动。
二、这块内容不显示,再从新显示时不滚动。就须要watch中添加如下方法:
query(newQuery) { if (!newQuery) { setTimeout(() => { this.$refs.shortcut.refresh(); }, 20); } }
一、scroll不能滚动:
组件从隐藏到显示,只有显示以后,dom才能被正确计算,这时候才须要从新计算better-scroll, 因此show的时候须要从新计算。
aSuncat: 播放记录列表仍是不能滚动,下次看看。
一、歌曲添加是经过action实现的。
一、aSuncat:点击add-song搜索出来的列表时没有跳转到播放页面
一、缓存中loadPlay方法获取到的song有song的属性,可是没有song的实例
一、add-song的display:none的时候,scroll就已经初始化了,因此滚动高度不对,须要在add-song的show的时候,从新refresh();
一、playlist、search-list:删除一首歌有100毫秒的动画,而20毫秒后动画就从新计算了,这样就会致使滚动的高度出现错误。由于100毫秒后才是最终的高度。
解决:scroll组件的延迟计算高度时间能够自由传入,prop传入。
二、都须要修改refreshDelay:playlist.vue、包裹search-list的组件:search.vue、add-song
一、回退到上一级:this.$router.back();
一、aSuncat:“最近听的”,没法滚动。
一、@play="ready"
,而不是@canplay="ready"
, 这样能保证this.timer的play()先执行,而后触发ready为true,这样切换的时候再点暂停,audioPause就在play()以后了。
一、引入的库都会打包到vendor.js, 打包的300k,线上开启gZip后,不到100k,主要不修改依赖,vendor的哈希值都是不变的,线上的话能被缓存下来。
二、app.js能进行优化。
三、利用express启用了一个服务,开启了9000端口。
四、执行node prod.server.js
, server就被启动起来了。
五、manifest是维护静态资源的一个清单。
六、模拟线上运行。
(1)项目根目录建立prod.server.js
。
(2)
var express = require('express'); var config = require('./config/index'); var axios = require('axios'); /* 跨域*/ var app = express(); var apiRoutes = express.Router(); apiRoutes.get('/getDiscList', (req, res) => { var url = 'https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg' axios.get(url, { headers: { 'content-type': 'application/x-www-form-urlencoded', 'referer': 'https://c.y.qq.com/', 'host': 'c.y.qq.com' }, params: req.query }).then((response) => { console.log(response) res.json(response.data) }).catch((e) => { consle.log(e) }) }); app.use('/api', apiRoutes); /*入口*/ app.use(express.static('./dist')); /*端口号监听*/ var port = process.env.PORT || config.build.port; module.exports = app.listen(port, function(err) { if (err) { console.log(err); return; } console.log('listening at http://localhost:' + port + '\n'); })
(3)控制台输入node prod.server.js
;便能运行了。
一、优化app.js:路由组件异步加载(路由懒加载),官网的“路由懒加载”有说起。
require.ensure是1.0x说起的语法,2.0x的时候有code splitting·Async, 提供dynamic import(动态加载)。首屏资源加载会变得不多。
二、路由异步加载(code spliting技术)后,vendor.js不会变,app.js变小,以前80多k,如今50多k。
三、实际项目中,若是用到cdn,须要配置public-path,
一、package.json里的vue的版本号和vue-template-compiler的版本号必定要一致。
一、移动端调试工具:vConsole。
二、抓包工具:charles(mac),fiddler(windows).
charles默认有个8888的端口。
三、charles对iphone抓包配置:https://blog.csdn.net/qq_1290259791/article/details/80793029
20190327(未看完):《imooc-vue.js源码全方位解析》 |
1、vuejs源码并不全是用es6写的。
2、vue技术揭秘:https://ustbhuangyi.github.io/vue-analysis/
1、flow是facebook出品的javascript静态类型检测工具,vue.js的源码利用了flow作了静态资源检查,因此了解flow有助于咱们阅读源码。
2、
一、安装flow:https://flow.org/en/docs/install/
(1)npm install --save-dev babel-cli babel-preset-flow
(2)./node_modules/.bin/babel src/ -d lib/
(3)npm install --save-dev flow-bin
(4)npm run flow init
(5)npm run flow
(6).babelrc package.json .flowconfig 配置
3、flow的libdef概念,能够识别第三方库或者是自定义类型,vue.js也是利用了这一特性。
1、src/ compiler:编译相关的代码
template to render function相关逻辑在compiler里。
2、src/ core/ global/ mixin.js等
src/ core/ instance: vue 生命周期
src/ core/ observer 响应式相关
src/ core/ util: 工具、方法
src/ core/ vdom: virtual dom
3、platforms: web、 weex
能够编译出在浏览器运行的框架
4、server:服务端代码
5、经过rollup把上述这些js打包成一个单独的js
1、vue.js源码是基于rollup构建的
2、 gulp、grunt:以业务为基准的。
3、path.resolve是nodejs提供的方法
1、vue其实是一个类,类上挂了不少原型方法。
2、vue的util方法不建议外面的库去使用,由于里面的方法不是很稳定。
3、keepAlive是一个内置组件。
4、vue初始化过程:
一、找到vue的定义:instance/ index.js
二、vue是一个class,经过mixin给vue原型挂载不少原型方法。
三、initGlobalAPI给vue挂载不少静态方法。
1、数据驱动:视图是由数据驱动生成的。对视图的修改,不会直接操做dom。
2、vm.$mount(options),模板才被编译成视图
1、vue不能够挂载到html或body,会被覆盖,因此用#app
1、被编译生成的render函数使用的方法:vm_.c
手写的render函数使用的:vm.$createElement
var app = new Vue({ el: '#app', render(createElement) { return createElement('div', { attrs: { id: 'app1' } }, this.message); }, data() { return { message: 'hello vue' } } })
1、虚拟dom的定义:src/ vdom/ vnode.js
2、flow/ vnode.js/ VNodeData能获得vnode数据类型
3、vdom是参考开源库snabbdom的实现
4、vnode只是用来映射到真实dom的渲染,不须要包含操做dom的方法,所以很是轻量和简单。
1、函数柯里化:假如一个函数只能收一个参数,那么这个函数怎么实现加法呢,由于高阶函数是能够当参数传递和返回值的,因此问题就简化为:写一个只有一个参数的函数,而这个函数返回一个带参数的函数,这样就实现了能写两个参数的函数了——这就是所谓的柯里化(Currying,以逻辑学家Hsakell Curry命名),也能够理解为一种在处理函数过程当中的逻辑思惟方式。
1、
Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub;
2、data原先只有一个on,installComponentHooks执行以后多了一个hook,
hook中有destroy, init, insert, depatch
3、componentOptions的children,在插槽的时候会用到
1、patch的结果返回的是一个dom
2、整个插入过程是先子后父。
3、可用debugger调试源码断点
1、patch流程:createComponent -> 子组件初始化 -> 子组件render -> 子组件patch
2、activeInstance为当前激活的vm实例;vm.$vnode为组件的占位vnode,vm._node为组件的渲染vnode
3、嵌套
1、外部调用场景下的合并配置是经过mergeOption,并遵循必定的合并策略。
2、组件合并是经过initInternalComponent,它的合并更快。
3、框架、库的设计都是相似,自身定义了默认配置,同事能够在初始化阶段传入配置,而后merge配置,来达到定制化不一样需求的目的。