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