zoukankan      html  css  js  c++  java
  • 《vuejs快跑构建触手可及的高性能web应用》读书笔记

    1.cdn:内容分发网络(CDN)是将资源托管到全世界各处的服务器上以实现快速分发。CDN版本对于开发和快速验证比较有用,但是将unpkg应用于生产环境前,需要检查它是否适合你。

     

    2.假值包括false、undefined、null、‘’、NAN。

     

    3.使用v-show两个场景:

      频繁切换某些内容;

      如果元素包含任何图片,那么仅使用css隐藏父节点可以使浏览器在图片显示之前就加载它,这意味着一旦v-show变成真值,图片就可以显示出来。如果是v-if指令,图片就直到要显示时才开始加载。

     

    4.响应式如何实现:

      vue修改了每个添加到data上的对象,当该对象发生变化时vue会收到通知,从而实现响应式。对象的每个属性会被替换为getter和setter方法,因此可以像正常对象一样使用它,但当你修改这个属性时,vue会知道它发生了变化。

    5.为对象添加新的属性。

      因为getter,settter方法是在vue实例初始化的时候添加的,只有已经存在的属性是响应式的,当为对象添加一个新的属性的时候,直接添加并不会使这个属性成为响应式的。

    1 const vm = new Vue({
    2   data: {
    3     formData: { 
    4       username: 'someuser'
    5     }
    6   }
    7 });

      有几种方法解决这个问题:

      (1)最简单的办法是在初始化时对象上定义这个属性,并把它的值设置为undefined。上例中的formData对象会变成下面这样:

    1 formData: {
    2     username: 'someuser',
    3     name: undefined   
    4 }

      (2) 也可以使用Object.assign()来创建一个新的对象然后覆盖原来对象,当需要一次性更新多个属性时,这是最有效的方法:

    1 vm.formData = Object.assign({}, vm.formData, {
    2     name: 'Some User'
    3 });

      (3)Vue还提供了Vue.set()方法,可以使用它将属性设置为响应式的:

    1 Vue.set(vm.formData, 'name', 'Some User');

      在组件内部也可以使用this.$set来调用这个方法。

    6.设置数组的元素

      不能直接使用索引来设置数组的元素。下面的做法是行不通的:

    1 const vm = new Vue({
    2     data: {
    3         dogs: ['Rex', 'Rover', 'Henrietts', 'Alan']
    4     }
    5 });
    6 vm.dogs[2] = 'Bob'

      有两种方法可以解决这一问题。一种是使用.splice( )方法移除旧元素并添加新元素:

    vm.dogs.splice(2, 1, 'Bob');

      另一种是使用Vue.set( ):

    Vue.set(vm.dogs, 2, 'Bob');

    7.设置数组的长度

      在javascript中,可以设置一个数组的长度,自动让空元素填充数组至该长度或者截掉数组的尾部。不过这个方法不能用于处理data对象中的数组,因为Vue不能检测到该操作对数组的任何更改。

     

    8.到目前为止已经了解如何将数据输出到模板,以及vue的响应式能力如何做到让模板随着数据的跟新而更新。但这只是单向数据绑定。试着运行下面的代码,你会发现inputText会保持不变。输入框下面的文本也会保持不变。

     1 <div id="app">
     2   <input type="text" :value="inputText">
     3   <p>inputText: {{inputText}}</p>
     4 </div>
     5 <script>
     6   new Vue({
     7     el: '#app',
     8     data: {
     9        inputText: 'initial value'
    10     }
    11   })
    12 </script>

    可以使用v-model指令,它作用于输入框元素,将输入框的值绑定到data对象的对应属性上,因此输入框不但会接收data上的初始值,而且当输入框内容更新时,data上的属性值会被更新。

     1   <div id="app">
     2      <input type="text" v-model="inputText">
     3      <p>inputText: {{inputText}}</p>
     4   </div>
     5   <script>
     6     new Vue({
     7        el: '#app',
     8        data: {
     9           inputText: 'initial value'
    10        }
    11     })
    12  </script>

        

    9.method妙用

    (1)将代表状态的数字-转换为可读的、描述真实状态的字符串

     1 <div id="app">
     2     <p>当前状态: {{statusFromId(status)}}</p>
     3 </div>
     4  <script>
     5         new Vue({
     6         el: '#app',
     7         data: {
     8         status: 2
     9         },
    10         methods: {
    11         statusFromId(id) {
    12            const status = ({
    13                0: '睡觉',,
    14             1: '吃饭',,
    15             2: '学习vue'
    16            })[id];
    17            return status || '未知状态:' +id;
    18             }
    19         }
    20     })
    21  </script>

    (2)过滤for循环中的数据,避免v-for和v-if混用

     1 <div id="app">
     2     <ul>
     3         <li v-for="number in filterPositive(numbers)">{{number}}</li>
     4     </ul>
     5 </div>
     6 <script>
     7     new Vue({
     8         el: '#app',
     9         data: {
    10             numbers: [-5, 0, 2, -1, 1, 0.5]
    11         },
    12         methods: {
    13             filterPositive(numbers) {
    14                 return numbers.filter((number)=> number > 0);  // [2, 1, 0.5]
    15             }
    16         }
    17     })
    18 </script>

    10. 在vue2.0中,mounted钩子触发时并不保证元素已经被添加到DOM上。如果想保证元素已经被添加,可以调用Vue,nextTick()方法,也可以通过this.$nextTick()调用,并传入一个回调函数,在回调函数中添加需要在元素被添加到DOM之后运行的代码。

     1 <div id="app">
     2     <p>Hello world</p>
     3 </div>
     4 <script>
     5     new Vue({
     6         el: '#app',
     7         mounted() {
     8             // 元素可能还没添加到DOM上
     9             this.$nextTick(()=>{
    10                  // 确定元素已经被添加到DOM上了
    11             })
    12         }
    13     })
    14 </script>       

    11. 使用自定义指令directive, 来实现一个闪烁效果:

     1 <body>
     2   <div id="app">
     3     <p v-blick>我会闪烁</p>
     4   </div>
     5 </body>
     6 <script>
     7   new Vue({
     8     el: '#app',
     9     data: {},
    10     directives: {
    11       'blick': {
    12           bind(el) {
    13               let isVisible = true;
    14               setInterval(() => {
    15                   isVisible = !isVisible;
    16                   el.style.visibility = isVisible ? 'visible' : 'hidden';
    17               }, 1000)
    18           }
    19       }
    20     }
    21   })
    22 </script>

     12. prop使用和.sync修饰符

      如果prop的值不是字符串,那么就必须使用v-bind指令。

    <display-number :number = "10"></display-number>

      数据通过prop从父级组件传递给子组件中,当父级组件中的数据更新时,传递给子组件的prop也会更新。但是你不可以在子组件中修改prop。这就是所谓的单向下行绑定,防止子组件在无意中改变父级组件的状态。

      然而,双向数据绑定在某种情况下可能很有用。如果想要使用双向绑定,可以使用一个修饰符来实现 : .sync修饰符。它只是一个语法糖:

    <count-from-number :number.sync="numberToDisplay" />

    13.自定义输入组件与v-model

    与.sync修饰符相似,可以在组件上使用v-model指令来创建自定义输入组件。这里同样也是一个语法糖。请看示例:

    <input-username  v-model="username" /> 

    上面的代码等效于:

    <input-username :value="username"  @input="value => username=value" />

    14.响应路由变化

      当/user/1234 与/user/5678 相互切换时,其中相同的组件会被重用,于是第一章所涉及到的生命周期钩子,诸如mounted,都不会被调用。不过,你可以使用beforeRouteUpdate导航守卫在URL动态部分变化时运行一些代码。

     我们创建一个PageUser组件,它在挂载的时候会调用一次API,并且在路由变化时还会再调用一次:

    <template>
        <div v-if="state === 'loading'">
            loading user...
        </div>
        <div>
           <h1>user: {{userInfo.name}}</h1>
        </div>
    </template>
    
    <script>
        export default {
            data: ()=> ({
                 state: 'loading',
                 userInfo: undefined
            }),
            mounted() {
                 this.init();
            },
            beforeRouteUpdate(to, from, next) {
                 this.state = 'loading';
                 this.init();
                 next();
            },
            method: {
                init() {
                     fetch(`/api/user/${this.$route.params.userId}`)
                     .then((res)=> res.json())
                     .then((data)=> {
                          this.userInfo = data;
                     });}
               }
           }
       }
    </script>                                   

    15.路由参数作为组件属性传入

    除了在组件中使用this.$route.params,还可以让vue-router将params作为路由组件的props传入。以如下组件为例:

    const PageUser = { 
        template: '<p>ID: {{ $route.params.userId }}</p>'
    };
    const router = new VueRouter({
        routes: [{
             path: '/user/:userId ',
             component: PageUser 
        }]
    });

    当导航至/user/1234的时候,‘ID:1234’就会被输出到页面上。

    要想让vue-router改为将userId作为组件的一个属性传入,你可以在路由中指定props:true

    const PageUser = {
         props: ['userId],
         template: '<p>user ID: {{ userId }}</p>'
    };
    const router = new VueRouter({
         routes: [
              path: '/user/:userId',
              component: PageUser,
              props: true
         ]
    });

    使用props代替$route.$params的好处是:组件与vue-router不再紧密耦合。设想一下,将来你想在一个页面上展示多个用户,使用第一个例子的代码就会很棘手,但使用第二个例子的代码就会变得很简单,因为只要在另一个页面调用该组件就好了,就像它是一个与路由无关的通用组件那样。

    16.vue-router中的tag属性

    <router-link to="/user/1234" tag="li">go to user 1234</router-link>

    这会在页面上渲染出如下结果:<li> go to user 1234 </li>

    由此,在它上面悬停也就不会给你带来任何关于这个链接的消息,也不能通过鼠标右键在新窗口打开这个链接;

    为了解决这个问题,可以在<router-link>元素里面加上锚点标签:

    <router-link to="/user/1234" tag="li"><a>go to user 1234</a></router-link>

    现在,渲染出来的html就是下面这样:

    <li><a href="/user/1234" >go to user 1234</a></li>

    如果想给<router-link>添加一个事件处理器,可以使用.native修饰符来监听:

    <router-link to="/blog" @click.native="handleClick">blog</router-link>

    17.导航守卫

    当你维护的是一个拥有大量路由的网站,于是会发现另一个很有用的特性,它就是路由元信息。你可以在路由上添加一个meta属性,并在守卫那里重新获取它。例如,在account路由上设置一个requiresAuth属性,然后在守卫中查看该属性:

    const router = new VueRouter({ 
        routes: [{
             path: '/account',
             component: PageAccount,
             meta: {
                 requiresAuth: true
            }
        }]
    });
    
    router.beforeEach((to, from, next)=> {
         if (to.meta.requiresAuth) {
              next('/login');
         } else {
              next();
         }
    })

    当使用嵌套路由时,to.meta指向的是子路由的元信息,而非其父路由。也就是说,如果你在/account上添加了meta对象,而用户访问的是/account/email,则所获得的meta对象是关于该子路由的,而非父路由。可以通过遍历to,matched的方式来曲线救国,

    它同样也包含了父路由的元信息:

    router.beforeEach((to, from, next) => {
      const requiresAuth = to.matched.some((record) => {
         return record.meta.requiresAuth;
      })
      if (to.meta.requiresAuth) {
         next('/login');
      } else {
         next();
      }
    })

    18.afterEach,可用于设置页面标题

    const router = new VueRouter({
      routes: [{
         path: '/blog',
         components: PageBlog,
         meta: {
             title: 'welcome to my blog'
         }
      }]
    });
    router.afterEach((to) => {
       document.title = to.meta.title;
    });

    19.使用vuex和websocket,实现用户在页面上所拥有的的消息数量

    组件代码:

    const NotificationCount = {
      template: `<p>messages: {{messageCount}}</p>`,
      computed: {
         messageCount() {
           return this.$store.state.messages.length;
         }
      },
      mounted() {
        this.$store.dispatch('getMessages');
      }
    };

    然后下面使我们的vuex store(store/index.js)

    let ws;
    export  default  new Vuex.Store({
      state: {
         messages: []
      },
      mutations: {
         setMessages (state, messages) {
            state.messages = messages;
         }
      },
      actions: {
         getMessages ({ commit }) {
           if (ws) { return ; }
              ws = new WebSocket('/api/message');
              ws.addEventListener('message', (e)=> {
                 const data = JSON.parse(e.data);
                 commit('setMessages ', data.message);
              });
           }
        }
    });             

    阮一峰webSocket 教程: http://www.ruanyifeng.com/blog/2017/05/websocket.html?utm_source=tuicool&utm_medium=referral

    实例对象的onmessage属性,用于指定收到服务器数据后的回调函数。

     

     

  • 相关阅读:
    解读AppIcon图标设置置信息和App内存警告临界值
    我在外包公司做增删改查有前途么?
    浅议Grpc传输机制和WCF中的回调机制的代码迁移
    2019.NET Conf China(中国.NET开发者峰会)活动全纪录:.NET技术之崛起,已势不可挡
    一位年轻而优秀的.NET开发者的成长点滴
    领域驱动设计-让程序员心中有码(九)
    2019.NET Conf,我们在共同期待
    码农的技术小世界
    .NET Core使用gRPC打造服务间通信基础设施
    坚持写了一年的博客,我有哪些收获
  • 原文地址:https://www.cnblogs.com/guwufeiyang/p/12895159.html
Copyright © 2011-2022 走看看