004--自找麻烦之 vue2.0

人的差异其实很小:一,你在犹豫,他在做,所以他比你成功机会多;二,你在找借口,他在解决问题,所以他比你事业有成;三,你在消费,他在理财,所以他比你更富足;四,你在算计自己的利益,他在考虑对方的利益,所以他比你更加有人脉。成功没有奇迹,只有轨迹!

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">&#xe624;</span>

    &#xe624;  是一种图标的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)就行了)











        



















猜你喜欢

转载自blog.csdn.net/m0_37291785/article/details/80044671