编程语言总结vue知识体系之实用技巧

    作者:lzg更新于: 2020-03-09 22:58:07

    大神带你学编程,欢迎选课

    总结vue知识体系之实用技巧.编程语言往往使程序员能够比使用机器语言更准确地表达他们所想表达的目的。对那些从事计算机科学的人来说,懂得程序设计语言是十分重要的,因为在当今所有的计算都需要程序设计语言才能完成。

    vue 作为目前前端三大框架之一,对于前端开发者可以说是必备技能。那么怎么系统地学习和掌握 vue 呢?为此,我做了简单的知识体系体系总结,不足之处请各位大佬多多包涵和指正,如果喜欢的可以点个小赞!本文主要讲述一些vue开发中的实用技巧。

    编程语言总结vue知识体系之实用技巧_编程语言_计算机_前端开发 _课课家件的生命周期

    比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,常规的写法可能如下:

    1.  // Parent.vue 
    2. <Child @mounted="doSomething"/> 
    3.  
    4. // Child.vue 
    5. mounted() { 
    6.   this.$emit("mounted"); 

    此外,还有一种特别简单的方式,子组件不需要任何处理,只需要在父组件引用的时候通过@hook 来监听即可,代码如下:

    1. <Child @hook:mounted="doSomething" /> 
    2. <Child @hook:updated="doSomething" /> 

     

    当然这里不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以。

    watch 的初始立即执行

    观察和响应 Vue 实例上的数据变动。类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作。

    但是当 watch 一个变量的时候,初始化时并不会执行,如下面的例子,你需要在 created 的时候手动调用一次。

    1. created() { 
    2.   this.getList(); 
    3. }, 
    4. watch: { 
    5.   keyWord: 'getList', 

    上面这样的做法可以使用,但很麻烦,我们可以添加 immediate 属性,这样初始化的时候就会自动触发(不用再写 created 去调用了),然后上面的代码就能简化为:

    1. watch: { 
    2.   keyWord: { 
    3.     handler: 'getList', 
    4.     immediate: true 
    5.   } 

    watch 有三个参数:

    • handler:其值是一个回调函数。即监听到变化时应该执行的函数
    • deep:其值是 true 或 false;确认是否深入监听。
    • immediate:其值是 true 或 false,确认是否以当前的初始值执行 handler 的函数

    路由参数变化组件不更新

    同一path的页面跳转时路由参数变化,但是组件没有对应的更新。

    原因:主要是因为获取参数写在了created或者mounted路由钩子函数中,路由参数变化的时候,这个生命周期不会重新执行。

    解决方案1:watch监听路由

    1. watch: { 
    2.  // 方法1 //监听路由是否变化 
    3.   '$route' (to, from) { 
    4.    if(to.query.id !== from.query.id){ 
    5.             this.id = to.query.id; 
    6.             this.init();//重新加载数据 
    7.         } 
    8.   } 
    9. //方法 2  设置路径变化时的处理函数 
    10. watch: { 
    11. '$route': { 
    12.     handler: 'init', 
    13.     immediate: true 
    14.   } 

    解决方案2 :为了实现这样的效果可以给router-view添加一个不同的key,这样即使是公用组件,只要url变化了,就一定会重新创建这个组件。

    1. <router-view :key="$route.fullpath">router-view> 

     

    路由懒加载

    Vue 项目中实现路由按需加载(路由懒加载)的 3 中方式:

    1. // 1、Vue异步组件技术: 
    2.  { 
    3.     path: '/home', 
    4.     name: 'Home', 
    5.     component: resolve => reqire(['path路径'], resolve) 
    6.   } 
    7.  
    8. // 2、es6提案的import() 
    9.   const Home = () => import('path路径') 
    10.  
    11. // 3、webpack提供的require.ensure() 
    12.   { 
    13.      path: '/home', 
    14.      name: 'Home', 
    15.      component: r => require.ensure([],() =>  r(require('path路径')), 'demo') 
    16.     } 

    require.context()

    require.context(directory,useSubdirectories,regExp)

    • directory:说明需要检索的目录
    • useSubdirectories:是否检索子目录
    • regExp:匹配文件的正则表达式,一般是文件名

    场景:如页面需要导入多个组件,原始写法:

    1. import titleCom from '@/components/home/titleCom' 
    2. import bannerCom from '@/components/home/bannerCom' 
    3. import cellCom from '@/components/home/cellCom' 
    4. components: { 
    5.   titleCom, bannerCom, cellCom 

    这样就写了大量重复的代码,利用 require.context 可以写成

    1. const path = require('path') 
    2. const files = require.context('@/components/home', false, /\\.vue$/) 
    3. const modules = {} 
    4. files.keys().forEach(key => { 
    5.   const name = path.basename(key, '.vue') 
    6.   modules[name] = files(key).default || files(key) 
    7. }) 
    8. components: modules 

    递归组件

    递归组件: 组件在它的模板内可以递归的调用自己,只要给组件设置 name 组件就可以了。

    不过需要注意的是,必须给一个条件来限制数量,否则会抛出错误: max stack size exceeded

    组件递归用来开发一些具体有未知层级关系的独立组件。比如:联级选择器和树形控件

    1. <template> 
    2.   <div v-for="(item,index) in treeArr"> {{index}} <br/> 
    3.       <tree :item="item.arr" v-if="item.flag">tree> 
    4.   div> 
    5. template> 
    6. <script> 
    7. export default { 
    8.   // 必须定义name,组件内部才能递归调用 
    9.   name: 'tree', 
    10.   data(){ 
    11.     return {} 
    12.   }, 
    13.   // 接收外部传入的值 
    14.   props: { 
    15.      item: { 
    16.       type:Array, 
    17.       default: ()=>[] 
    18.     } 
    19.   } 
    20. script> 

     

    清除定时器或者事件监听

    由于项目中有些页面难免会碰到需要定时器或者事件监听。但是在离开当前页面的时候,定时器如果不及时合理地清除,会造成业务逻辑混乱甚至应用卡死的情况,这个时就需要清除定时器事件监听,即在页面卸载(关闭)的生命周期函数里,清除定时器。

    1. methods:{ 
    2.   resizeFun () { 
    3.     this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128 
    4.   }, 
    5.   setTimer() { 
    6.     this.timer = setInterval(() => { }) 
    7.   }, 
    8.   clearTimer() {//清除定时器 
    9.         clearInterval(this.timer) 
    10.     this.timer = null 
    11.     } 
    12. }, 
    13. mounted() { 
    14.   this.setTimer() 
    15.   window.addEventListener('resize', this.resizeFun) 
    16. }, 
    17. beforeDestroy() { 
    18.   window.removeEventListener('resize', this.resizeFun) 
    19.   this.clearTimer() 

    自定义路径别名

    我们也可以在基础配置文件中添加自己的路径别名

    1. resolve: { 
    2.     extensions: ['.js', '.vue', '.json'], 
    3.     alias: { 
    4.       'vue$': 'vue/dist/vue.esm.js', 
    5.       '@': resolve('src'), 
    6.       'assets': resolve('src/assets') 
    7.     } 
    8.   } 

    然后我们导入组件的时候就可以这样写:

    1. // import YourComponent from '/src/assets/YourComponent' 
    2. import YourComponent from 'assets/YourComponent' 

    这样既解决了路径过长的麻烦,又解决了相对路径的烦恼。

    动态给修改dom的样式

    原因:因为我们在写.vue文件中的样式都会追加scoped。这样针对模板dom中的样式就可以生效,但其生效后的最终样式并不是我们写的样式名,而是编码后的。比如:

    1. <template> 
    2.   <div class="box">domdiv> 
    3. template> 
    4. <style lang="scss" scoped> 
    5.   .box { 
    6.     background: red; 
    7.   } 
    8. style> 

     

    vue 将代码转译成如下,所以我们在js中拼接上的dom结构样式并不会生效。

    1. .box[data-v-11c6864c]{ background:red; } 
    2. <template> 
    3.   <div class="box" data-v-11c6864c>domdiv> 
    4. template> 

    解决方法:将要改变的样式写在非scoped样式标签中。

    长列表性能优化

    我们应该都知道 vue 会通过 object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间。

    所以,我们可以通过 object.freeze 方法来冻结一个对象,这个对象一旦被冻结,vue就不会对数据进行劫持了。

    1. export default { 
    2.   data: () => ({ 
    3.     list: [] 
    4.   }), 
    5.   async created() { 
    6.     const list = await axiOS.get('xxxx') 
    7.     this.list = Object.freeze(list) 
    8.   }, 
    9.   methods: { 
    10.     // 此处做的操作都不能改变list的值 
    11.   } 

    另外需要说明的是,这里只是冻结了 list 的值,引用不会被冻结,当我们需要 reactive 数据的时候,我们可以重新给 list 赋值。

    内容分发(slot)

    插槽 slot,也是组件的一块 HTML 模板,这一块模板显示不显示、以及怎样显示由父组件来决定。实际上,一个 slot 最核心的两个问题在这里就点出来了,是显示不显示和怎样显示。

    默认插槽

    又名单个插槽、匿名插槽,这类插槽没有具体名字,一个组件只能有一个该类插槽。

    1.  
    2. <template> 
    3.   <div class="parent"> 
    4.     <h1>父容器h1> 
    5.     <child> 
    6.       <div class="tmpl"> 
    7.         <span>菜单1span> 
    8.       div> 
    9.     child> 
    10.   div> 
    11. template> 
    12.  
    13.  
    14. <template> 
    15.   <div class="child"> 
    16.     <h1>子组件h1> 
    17.     <slot>slot> 
    18.   div> 
    19. template> 

     

    具名插槽

    匿名插槽没有 name 属性,所以叫匿名插槽。那么,插槽加了 name 属性,就变成了具名插槽。具名插槽可以在一个组件中出现 N 次,出现在不同的位置,只需要使用不同的 name 属性区分即可。

    1.  
    2. <template> 
    3.   <div class="parent"> 
    4.     <h1>父容器h1> 
    5.     <child> 
    6.       <div class="tmpl" slot="up"> 
    7.         <span>菜单up-1span> 
    8.       div> 
    9.       <div class="tmpl" slot="down"> 
    10.         <span>菜单down-1span> 
    11.       div> 
    12.       <div class="tmpl"> 
    13.         <span>菜单->1span> 
    14.       div> 
    15.     child> 
    16.   div> 
    17. template> 
    18.  
    19.  
    20. <template> 
    21.   <div class="child"> 
    22.      
    23.     <slot name="up">slot> 
    24.     <h3>这里是子组件h3> 
    25.      
    26.     <slot name="down">slot> 
    27.      
    28.     <slot>slot> 
    29.   div> 
    30. template> 

     

    作用域插槽

    作用域插槽可以是默认插槽,也可以是具名插槽,不一样的地方是,作用域插槽可以为 slot 标签绑定数据,让其父组件可以获取到子组件的数据。

    1.  
    2. <template> 
    3.   <div class="parent"> 
    4.     <h1>这是父组件h1> 
    5.     <child 
    6.       >> 
    7.       <template slot="default" slot-scope="slotProps"> 
    8.         {{ slotProps.user.name }} 
    9.       template> child 
    10.     >> 
    11.   div> 
    12. template> 
    13.  
    14.  
    15. <template> 
    16.   <div class="child"> 
    17.     <h1>这是子组件h1> 
    18.     <slot :user="user">slot> 
    19.   div> 
    20. template> 
    21. <script> 
    22.   export default { 
    23.     data() { 
    24.       return { 
    25.         user: { 
    26.           name: '小赵' 
    27.         } 
    28.       } 
    29.     } 
    30.   } 
    31. script> 
      编程语言原本是被设计成专门使用在计算机上的,但它们也可以用来定义算法或者数据结构。正是因为如此,程序员才会试图使程序代码更容易阅读。

课课家教育

未登录