人的差异其实很小:一,你在犹豫,他在做,所以他比你成功机会多;二,你在找借口,他在解决问题,所以他比你事业有成;三,你在消费,他在理财,所以他比你更富足;四,你在算计自己的利益,他在考虑对方的利益,所以他比你更加有人脉。成功没有奇迹,只有轨迹!
1. Vuex:用于各个组件的数据共享
2. Nuxt.js : 基于vue的服务端渲染应用框架
3. 任何一门框架的学习最好的资料就是官方文档
4. vue 不支持IE8以下的浏览器(记住)
5. 要在外面取vue实例app里面的data要用: app.$data
6. 学习vue只需要操作数据,不会再涉及到DOM的操作
7. vue的双向数据绑定原理(面试会问,重要,以后补充)
8. vue注册全局组件用 component ;子组件接收父组件的数据要用 props
Vue.component("TodoItem",{ props:['content'], template:"<li>{{content}}</li>" })
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
9. 子组件传递数据给父组件
10. 生命周期函数就是vue实例在某一个时间点会自动执行的函数
beforeCreate(vue实例进行部分初始化之后会执行);created(完全初始化之后执行);
beforeMount(模板结合vue实例的DOM元素挂载到页面之前执行),mounted(页面挂载之后 执行);
beforeDestroy(组件被销毁之前执行,在控制台调用 vm.$destroy() 时这个函数就执行),destroyed(组件被完全销毁之后执行);
beforeUpdate(当数据发生还没重新渲染之前执行),updated(当数据发生改变重新渲染之后执行)
11. vue指令里面的值不再是字符串,而是js表达式
12. v-text 和 v-html有点类似,区别在于v-text="name"(和 {{name}} 的用法一模一样)做了转义,完整输出内容,而v-html 可以识别html表达式
13. 计算属性 computed(非常重要的特点:内置缓存)的写法(写成函数,返回这个值)
new Vue({ ... computed:{ fullName:function(){ return this.fname + this.lname } } })
<div id="app">{{fullName}}</div>
14. computed 的 get (获取值时执行)和 set(设置值时执行)
new Vue({ ... computed:{ fullName:{ get:function(){ return this.fname + this.lname }, set:function(value){ var arr = value.split(" "); this.fname = arr[0]; this.lname = arr[1]; } } } })
15. div绑定某个类名用 :class="{activated: isActivated}" 取决于isActivated是true还是false
:class="[activated]" 这样写activated代表一个变量,变量的内容即是一个类名
16. Vue.set()不光能修改数据,还能添加数据,弥补了Vue数组变异方法的不足; Vue.set()在methods中也可以写成this.$set()
17. vue-cli 的使用
npm i -g vue-cli
vue init webpack Travel (Travel 表示项目放在哪个文件夹下)
基本回车操作,除了一些没见过的选项你不想安装就选择no
cd Travel
npm run dev
18. vue-cli 生成的项目文件分析
package-lock.json package的锁文件(帮助我们确定你安装的第三方包的版本,保持团队编程的统一)
.eslintrc.js 配置了一些代码的规范
.eslintignore 忽略某些文件的检测
.editorconfig 配置了编辑器的语法
static目录 图片,json数据等静态资源
src目录 整个项目的源代码
config目录 项目的配置文件
vue-cli生成的项目中, @ 符号代表 src 目录(这是在build目录中webpack.base.conf.js中帮我们设置好的)
19. 路由就是根据网址的不同,返回不同的内容给用户
20. <router-view></router-view> 显示当前路由地址所对应的内容
21. 单页应用通过js感知url的变化,动态删除再渲染新的DOM结构,把组件内容挂载到页面上,这时候路由是由前端来做的。
22. 单页应用首屏时间慢且SEO差(搜索引擎只认识HTMl当中的内容),多页应用首屏时间快且SEO好
23. 做移动端的页面可以写以下的语句防止用户用手缩放网页
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
24. reset.css 文件:对基础样式的修饰,保证所有浏览器显示的效果基本一致
border.css文件: 为了解决多倍屏1像素边框会被显示成多元素的问题 (1像素边框的解决方案)
npm i fastclick -S : fastclick用来解决移动端click时间300毫秒点击延迟的问题
25. iconfont 阿里巴巴矢量图标库: http://www.iconfont.cn/ (进入图标管理--我的项目--新建项目图标库)
26. 使用stylus: npm i stylus -s ; npm i stylus-loader -s
27. 只对当前组件的样式有效 scoped
<style scoped> </style>
28. iconfont的使用:选择需要图标加入购物车,添加至项目,下载到本地,再把iconfont.css 和四个字体文件(.eot,.svg,.ttf,.woff)提取出来,将iconfont.css文件中引用字体文件的路径改好就可以用了,例如:
<span class="iconfont"></span>
 是一种图标的16进制的字符标识 (可在iconfont的官网查看)
29. 在项目的build文件夹中的webpack.base.conf.js中为某些常见的路径配置变量别名,例如'styles':..
resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), 'styles': resolve('src/assets/styles'), } }
修改后要重启服务器才不会报错
30. 使用vue-awesome-swiper 来快速构建一个轮播 (新版本有点细节bug,采用老的版本 2.6.7)
github网址:https://github.com/surmon-china/vue-awesome-swiper
npm i [email protected] -s
<template> <div class="wrapper"> <swiper :options="swiperOption" v-if="showSwiper"> <swiper-slide v-for="item of list" :key="item.id"> <img class="swiper-img" :src="item.imgUrl" /> </swiper-slide> <div class="swiper-pagination" slot="pagination"></div> </swiper> </div> </template>
data () { return{ swiperOption: { pagination: '.swiper-pagination', loop: true, autoplay:fasle } } },
:options="swiperOption" 是 这个vue-awesome-swiper 的配置项,pagination是显示圆点,loop是循环播,autoplay是自动轮播
31. 当你要在子组件里面定义一个data的时候,data一定要是一个函数
32. 最好的防止网速太慢轮播图图片没加载完下面的元素抖动的方案 (用vw的话兼容性差)
.wrapper width: 100% height: 0 overflow: hidden padding-bottom: 31.25% background-color: #eee
33. style用了scoped后样式只对本组件生效,但是有时候又想让某些样式应用于其他组件,所以可以用 >>>
<style lang="stylus" scoped> .wrapper >>> .swiper-pagination-bullet-active background: #fff </style>
34. 谷歌浏览器下载一个插件 Vue.js devtools
35. 对超过div宽度的文字显示成 ... 的CSS写法
overflow: hidden
white-space: nowrap
text-overflow: ellipsis //ellipsis显示省略符号来代表被修剪的文本
36. 提到插槽的概念,不懂,后补
37. 数据请求推荐 axios
npm i axios -s
axios.get('/api/index.json') .then(this.getHomeInfoSucc)
38. vue-cli 生成的整个项目只有static目录里面的内容可以被外部访问到
39. vue-cli 生成的项目目录中 配置config文件夹下的index.js文件中的 module.exports
dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: { '/api':{ target: 'http://localhost:8080', pathRewrite: { '^/api':'/static/mock/' } } },
看 proxyTable 配置项,按如上配置 开发环境下的时候请求路径即使写的是 './api' ,它也会帮我们代理到 '/staic/mock'
这个功能是 webpack-dev-server 这个工具提供的
40. 父组件给子组件传值
<home-header :city="city"></home-header>
<script> export default { name: 'HomeHeader', props: { city: String } } </script>
<div class="header-right"> {{this.city}} <span class="iconfont arrow-icon"></span> </div>
41. 页面跳转用 <router-link to='/city'></router-link>
42. 原生app的上下拉动页面效果的插件(到顶部和底部还有弹性的效果) better-scroll 的使用:
https://github.com/ustbhuangyi/better-scroll
npm i better-scroll -s
<div ref="wrapper"> //要类似这种DOM结构,父div里面一个子div,子div里面再写页面的东西 <ul class="content"> <li>...</li> <li>...</li> ... </ul> <!-- you can put some other DOMs here, it won't affect the scrolling --> </div>
import Bscroll from 'better-scroll' export default { name: 'CityList', mounted () { this.scroll = new Bscroll(this.$refs.wrapper) //把DOM元素丢进去实例化 } } </script>
this.scroll.scrollToElement(element) //这个方法是用来将页面滚动到某个DOM元素的区域的
43. vue2 用 ref 来获取 DOM
<div class="touchscroll" ref='wrapper'></div>
this.$refs.wrapper
44. 兄弟组件之间的传值(兄传值给父,父再传给弟)
methods: { //兄 handleLetterClick (e) { this.$emit('change',e.target.innerText) } }
<city-list :cities="cities" :hot="hotCities" :letter="letter"></city-list> //父 <city-alphabet :cities="cities" @change="handleLetterChange"></city-alphabet>
handleLetterChange (letter) { //父 this.letter = letter }
props: { //弟 hot: Array, cities: Object, letter: String },
watch: { //弟 注意这一步要在watch里面处理这个传过来的数据 letter () { if (this.letter) { const element = this.$refs[this.letter][0] this.scroll.scrollToElement(element) } } }
45. vue中html元素中不要有逻辑的部分,例如
<li class="search-item border-bottom" v-show="!list.length">没有找到匹配数据</li> //v-show 这里要改在computed 里面
computed: { //改成这样 hasNoData() { return !this.list.length } }
<li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li> // 改成这样
46. Vuex 数据层框架的使用: 就是类似一个仓库,组件共用的数据存放在State里面,外面的组件要改变这个共用数据要通过dispatch方法来调用actions的异步代码调用commit方法来调用Mutations(转变)的同步代码最终mutate(变化)到state里面的数据,外面的组件也可以直接通过Mutations来改变state里面的数据
整个流程: 组件调用action,action调用mutations,Mutations去改变我们的数据
npm i vuex -s
vue-cli生成的项目中在src目录新建一个store文件夹/index.js文件
import Vue from 'vue' // index文件内容 import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { city: '北京' } })
import store from './store' //mian文件内容 ... new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })
<div class="header-right"> {{this.$store.state.city}} // 任何组件使用这个store上的共用数据的方法 <span class="iconfont arrow-icon"></span> </div>
以下是改变共享数据的过程;
methods: { //组件执行这个函数 dispatch方法去调用actions handerCityClick (city) { this.$store.dispatch('changeCity',city) } },
import Vue from 'vue' //这是store/index文件 actions触发Mutations最终改变state里面的city数据 import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { city: '北京' }, actions: { changeCity (ctx, city) { // console.log(city) ctx.commit('changeCity',city) } }, mutations: { changeCity (state, city) { state.city = city } } })
47. 编程式导航(路由通过js代码来实现页面路由的跳转了)
methods: { handerCityClick (city) { this.$store.commit('changeCity',city) this.$router.push('/') // 这样就跳转到首页了 } },
48. localstorage的用法
export default new Vuex.Store({ state: { city: localStorage.city || '北京' }, mutations: { changeCity (state, city) { state.city = city localStorage.city = city } } })
更健壮的兼容浏览器的写法(加入try catch 处理某些浏览器关闭本地存储功能代码会报错的问题)
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) let defaultCity = '汕头' try { if (localStorage.city) { defaultCity = localStorage.city } } catch (e) {} export default new Vuex.Store({ state: { city: defaultCity }, mutations: { changeCity (state, city) { state.city = city try { localStorage.city = city }catch (e) {} } } })49. 高级Vuex的api用法
import { mapState } from 'vuex' export default { name: 'HomeHeader', computed: { ...mapState(['city']) // 将state中共享数据映射到本组件的city数据身上 } }
<div class="header-right"> {{this.city}} //虽然这个city是共享数据,但是映射本组件就可以直接这样用了 </div>
50. 性能优化
<template> // 这个是App.vue 文件 <div id="app"> <keep-alive exclude="Detail"> //用这个标签在前进后退页面的时候就不会重复发送ajax请求,会缓存第一次发送的ajax请求 <router-view/> // exclude="Detail" 表示除了Detail组件不会缓存,其他都会缓存 </keep-alive> </div> </template>
activated () { // 重新显示页面比如说城市变了就要重新发送ajax请求就可以写在这个生命周期函数 activated 里面 if (this.lastCity !== this.city) { this.lastCity = this.city this.getHomeInfo() } }
51. vue中的 <router-link></router-link> 类似 a 标签,但想表示其他标签也可以
<router-link tag='div' to="/" class="header-abs"> // 加上 tag="div" 就可以表示 div 了,同样加上其他就可以表示其他标签 <div class="iconfont header-abs-back"></div> </router-link>
52. 获取当前页面滚动条的纵坐标位置:
document.documentElement.scrollTop;
53. 对全局事件的解绑
activated () { // 页面展示时执行 window.addEventListener('scroll',this.handleScroll) }, deactivated () { // 页面切换掉后执行 window.removeEventListener('scroll',this.handleScroll) }54. 递归组件的实现(vue中比较难的部分)(组件自己调用自己)
<template> <div> <div class="item" v-for="(item,index) of list" :key="index"> <div class="item-title border-bottom"> <span class="item-title-icon"></span> {{item.title}} </div> <div v-if="item.children" class="item-children"> // v-if 与 加上自己子项的类名区分 <detail-list :list="item.children"></detail-list> //用自己的组件名 </div> </div> </div> </template> <script> export default { name: 'DetailList', //组件名 props: { list: Array } }55. ajax请求要放在 mounted 这个钩子函数里面中请求
56. 解决切换页面时页面滚动到上一个页面的位置的问题(查看官网 -- 滚动行为)
import Vue from 'vue' // 这是router文件夹里面的 index.js 文件 import Router from 'vue-router' import Home from '@/pages/home/Home' import City from '@/pages/city/City' import Detail from '@/pages/detail/Detail' Vue.use(Router) export default new Router({ routes: [{ path: '/', name: 'Home', component: Home },{ path: '/city', name: 'City', component: City }, { path: '/detail/:id', name: 'Detail', component: Detail }], scrollBehavior (to, from, savedPosition) { //加上这段代码就可以解决 return { x: 0, y: 0} } })
57. 修改vue-cli生成的项目的package.json的启动配置项
"scripts": { "dev": "webpack-dev-server --host 0.0.0.0 --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "lint": "eslint --ext .js,.vue src", "build": "node build/build.js" },这样写就能通过ip地址访问webpack-dev启动的服务
58. vue项目的打包上线(针对vue-cli生成的项目)
npm run build 打包编译
把生成的dist目录中的东西给后端,扔到后端的根目录里面就行了
如果要运行在其他路径下
build: { // config文件夹下index.js (vue-cli项目) // Template for index.html index: path.resolve(__dirname, '../dist/index.html'), // Paths assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', assetsPublicPath: '/project/', //修改这里就可以使项目运行在后端的project路径下(当然要重新打包,然后把生成的dist目录修改成project)
59. 项目要请求其他端口或者域名下的接口数据:
module.exports = { dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: { '/api':{ target: 'http://localhost:80', // 前端服务跑在8080端口,后端服务器是80 就改成80就可以了 (其他域名就被整个域名改掉) pathRewrite: { '^/api':'/static/mock/' } } },
60. 行内设置样式
<div class="tiao" :style="{ width: item.jingdu}"></div>
61. router-link 标签上面绑定 @click会失效,要这样绑定
<router-link tag="div" to="before" class="wangqi yiyang" @click.native="beforeClick"> // 加上.native <div :class="{ 'active': !isBenqi }">往期成绩</div> </router-link>
另外 router-link 标签上的 to='before' 就是把当前路由链接最后一个改成before,如果加上 to='/before' 就是 跳到 /before 的路径下
62. 获取当前页面的路由url地址用 : this.$route.path
63. vue.js 刷新页面 自动执行某个点击事件可以使用vue的生命周期函数,如create或者mounted
64. 在vue中使用 Clipboard.js (页面复制文本到剪切板的)
git地址: https://github.com/zenorocha/clipboard.js
npm install clipboard --save
<script> import Clipboard from 'clipboard' // 引入 export default { name: 'Recharge', data () { return { // selected: '狗幣' dizhi: '56565DFlfdgkdflgkdflgkldfgldfgdllfs44544' } }, mounted () { const clipboard = new Clipboard('.zi') // 绑定要点击的那个按钮 clipboard.on('success',function(e){ // 复制成功或者失败的事件 alert("复制成功") e.clearSelection(); }); clipboard.on('error', function(e) { alert("复制失败!"); }); } } </script>
<div class="copy"> <div class="zi" data-clipboard-target=".dizhi">一键复制</div> //点击这个按钮,target那个属性是绑定要文本的目标 </div> <div class="dizhi">{{dizhi}}</div> // 要复制的文本的div
65. vue实现消息的无缝向上滚动效果: 参考 http://www.jb51.net/article/129733.htm (亲测可用)
66. destroyed 这个生命周期表示切换页面后执行,可以在这销毁一些定时器事件等
destroyed () { window.clearInterval(this.timeID); // 防止切换到其他组件页面报错 },(setInterval返回值相当于一个Id,每次执行都会产生一个特定的Id,返回值为数字,从一开始逐次累加,清除就是找到他的id然后 clearInterval(id)就行了)