zoukankan      html  css  js  c++  java
  • 1.31 Vue.js 学习总结 ( 一 )

    1.关于 render

      render这个函数,个人感觉就是让js直接写html和css,可以做到完全分离

      这里贴一下书上的代码示例,和我自己瞎搞的一个实例

      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4   <title></title>
      5 </head>
      6 <body>
      7 <style>
      8   .btn {
      9     outline: none;
     10     border: none;
     11     cursor: pointer;
     12     padding: 5px 12px;
     13   }
     14   .btn-text {
     15     color: #409eff;
     16     background-color: transparent;
     17   }
     18   .btn-text:hover {
     19     color: #66b1ff;
     20   }
     21 </style>
     22 <div id="app">
     23   <!-- 将实例中 fields & goods 传入组件 -->
     24   <fly-table :fields="fields" :goods="goods">
     25     <span slot="title">Fly Table Component</span>
     26   </fly-table>
     27 </div>
     28 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
     29 <script type="text/javascript">
     30   Vue.component('fly-table', {
     31     props: { // 组件接收外界传入的参数
     32       fields: {
     33         type: Array,
     34         default () {
     35           return []
     36         }
     37       },
     38       goods: {
     39         type: Array,
     40         default () {
     41           return []
     42         }
     43       }
     44     },
     45     methods: {
     46       reverse () { // 定义数组倒序方法
     47         this.goods.reverse()
     48       }
     49     },
     50     render (createElement) { // 使用render函数渲染DOM
     51       /**
     52        * createElement 可接收三个参数
     53        * 1. HTML标签字符串(String)| 组件选项对象(Object)| 节点解析函数(Function)
     54        * 2. 定义节点特性的对象(Object)
     55        * 3. 子节点,createElement构建的VNode节点或字符串生成的无标签文本节点(Array|String)
     56        */
     57       return createElement('div', {
     58         // * 作为子组件时的插槽名称
     59         slot: 'fly-table'
     60       }, [
     61         createElement('h2' ,this.$slots.title),
     62         createElement('button', {
     63           // class 用于绑定类名,同v-bind:class的绑定方式
     64           class: ['btn', 'btn-text'],
     65           // attrs 用于绑定节点一般属性,如id、disabled、title等
     66           attrs: {
     67             disabled: false,
     68             title: '点击使数组倒序'
     69           },
     70           // domProps 用于绑定节点DOM属性,如innerHTML、innerText等
     71           domProps: {
     72             innerText: '倒序'
     73           },
     74           on: {
     75             // 绑定事件,使用箭头函数以免创建函数作用域
     76             click: () => {
     77               this.goods.reverse()
     78             }
     79           },
     80           // 自定义指令
     81           directives: [],
     82           // 其他属性
     83           key: 'btnReverse',
     84           ref: 'btnReverse'
     85         }),
     86         createElement('table', {
     87           // style 用于绑定样式,同v-bind:style的绑定方式
     88           style: {
     89              '400px',
     90             textAlign: 'left',
     91             lineHeight: '42px',
     92             border: '1px solid #eee',
     93             userSelect: 'none'
     94           }
     95         }, [
     96           createElement('tr', [
     97             this.fields.map(field => createElement('th', field.prop))
     98           ]),
     99           this.goods.map(item => createElement('tr', {
    100             style: {
    101               color: item.isMarked ? '#ea4335' : ''
    102             }
    103           }, this.fields.map(field => createElement('td', {
    104             style: {
    105               borderTop: '1px solid #eee'
    106             }
    107           }, [
    108             field.prop !== 'operate' // 如果不是操作列,显示文本
    109               ? createElement('span', item[field.prop])
    110               : createElement('button', { // 否则显示按钮
    111                 class: ['btn', 'btn-text'],
    112                 domProps: {
    113                   innerHTML: '<span>切换标记</span>'
    114                 },
    115                 on: {
    116                   click: () => { // 当按钮被点击时,切换该行文本标记状态(被标记时字体颜色为红色)
    117                     item.isMarked = !item.isMarked
    118                   }
    119                 }
    120               })
    121           ]))))
    122         ])
    123       ])
    124     }
    125   })
    126   // 声明 Vue 实例
    127   let vm = new Vue({
    128     el: '#app',
    129     data () {
    130       return {
    131         fields: [
    132           {
    133             label: '名称',
    134             prop: 'name'
    135           },
    136           {
    137             label: '数量',
    138             prop: 'quantity'
    139           },
    140           {
    141             label: '价格',
    142             prop: 'price'
    143           },
    144           {
    145             label: '',
    146             prop: 'operate'
    147           }
    148         ],
    149         goods: [
    150           {
    151             name: '苹果',
    152             quantity: 200,
    153             price: 6.8,
    154             isMarked: false
    155           },
    156           {
    157             name: '西瓜',
    158             quantity: 50,
    159             price: 4.8,
    160             isMarked: false
    161           },
    162           {
    163             name: '榴莲',
    164             quantity: 0,
    165             price: 22.8,
    166             isMarked: false
    167           }
    168         ]
    169       }
    170     }
    171   })
    172 </script>
    173 </body>
    174 </html>
    View Code
     1 <!DOCTYPE html>
     2 <html lang="zh-CN">
     3 
     4 <head>
     5     <meta charset="UTF-8">
     6     <title>Document</title>
     7     <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
     8 </head>
     9 <style>
    10     .test{
    11         color: coral;
    12     }
    13     #slot-title{
    14         color: pink;
    15     }
    16 </style>
    17 <body>
    18     <div id="app">
    19         <test :msg="msg">
    20             <span id="slot-title" slot="title">this is a ttile</span>
    21         </test>
    22     </div>
    23 </body>
    24 
    25 <script>
    26     Vue.component('test', {
    27         props: {
    28             msg: {
    29                 type: String,
    30                 default() {
    31                     return []
    32                 }
    33             }
    34         },
    35         render: function (createElement) {
    36             return createElement('div', {
    37                 class: ["test"]
    38                 // domProps:{
    39                 //     innerText:'hello world'
    40                 // }
    41             }, [
    42                 createElement("h2",this.$slots.title),
    43                 // createElement("h2",{
    44                 //     slot:"",
    45                 //     style:{
    46                 //         color: ""
    47                 //     }
    48                 // }),  // 这个好像没有用
    49                 createElement("div", {
    50                     domProps: {
    51                         innerText: this.msg
    52                     }
    53                 })
    54             ])
    55         }
    56     })
    57     var vm = new Vue({
    58         el: '#app',
    59         data() {
    60             return {
    61                 msg: 'this is created by [render]'
    62             }
    63         },
    64         methods: {}
    65     });
    66 </script>
    67 
    68 </html>
    View Code

      简单来说,render 里面就是一个 不断套娃 的过程,正如html的标签一样,盒子套盒子,整吐了都

      render ( createElement ) 中 createELement 的参数 ( 第一个 通常就是 html标签类型 | 第二个是一个对象,里面是下图的一些属性 | 第三个 通常是一个数组 装的是createElement方法  /* 套娃 */  )

      

      如果看完了上面的代码,可能就会有一个简单的概念,然后我们深入一下

      有没有想过 render 里面的 createElement 到底返回的是什么,其实可以这样理解

        每有一个 createElement 就有一个 VNode

      官网的解释

      

      然后是 VNode的约束,即 

      

      书上有一句看似不起眼的话

        “ 最后一点,在组件树中,VNode 必须保持其身份的唯一,以便 Vue 一一对应地对每一个真实的 DOM 节点进行追踪。 ”

      其实 我认为 就是 重复的 VNode 就没办法好好更新 真实的 DOM

     2.关于 filter

      {{ msg | dealMsg_1 | dealMsg_2 }}  用管道符号搞的这种,就是filter 而且应该是 

        从左往右,依次递交

          

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <title></title>
     5 </head>
     6 <body>
     7 <div id="app">
     8   <h1>{{ title }}</h1>
     9   <h1>{{ title | supplyTitle1 }}</h1>
    10   <!-- 存在多个filter时,将从左向右执行 -->
    11   <h1>{{ title | supplyTitle1 | supplyTitle2 }}</h1>
    12 </div>
    13 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
    14 <script type="text/javascript">
    15   let vm = new Vue({
    16     el: '#app',
    17     data () {
    18       return {
    19         title: 'Test#%for#%Filter.'
    20       }
    21     },
    22     filters: {
    23       supplyTitle1 (value) { // 表达式的值将作为形参传入
    24         console.log('Supply Title 1')
    25         return value.replace(/#/g, ' ')
    26       },
    27       supplyTitle2 (value) {
    28         console.log('Supply Title 2')
    29         return value.replace(/%/g, '')
    30       }
    31     }
    32   })
    33 </script>
    34 </script>
    35 </body>
    36 </html>
    View Code

    3.关于 el,template , render 的顺序

      render > template > el

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <title></title>
     5 </head>
     6 <body>
     7 <div id="app">
     8   <h1>el: {{ msg }}</h1>
     9 </div>
    10 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
    11 <script type="text/javascript">
    12   let vm = new Vue({
    13     el: '#app',
    14     render (c) {
    15       return c('h1', 'render: ' + this.msg)
    16     },
    17     template: '<h1>template: {{ msg }}</h1> ',
    18     data () {
    19       return {
    20         msg: 'I want you!'
    21       }
    22     }
    23   })
    24 </script>
    25 </body>
    26 </html>
    View Code

    4.对于 mixin与实例的冲突与合并

       

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <title></title>
     5 </head>
     6 <body>
     7 <style>
     8   #app {
     9     color: #2c3e50;
    10     font-family: Roboto, sans-serif;
    11   }
    12   .label {
    13     display: inline-block;
    14     min-width: 160px;
    15   }
    16 </style>
    17 <div id="app">
    18   <h1>{{ title }}</h1>
    19   <p><strong class="label">Text:</strong>{{ text }}</p>
    20   <p><strong class="label">Plus Text:</strong>{{ plusText }}</p>
    21   <p><strong class="label">Upper Text:</strong>{{ text | supplyUpper }}</p>
    22   <button @click="toggleText">切换文本</button>
    23 </div>
    24 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
    25 <script type="text/javascript">
    26   // 强耦合,需要被混入组件的data根节点中包含text属性
    27   let mixin = {
    28     data () {
    29       return {
    30         title: 'Test for mixin'
    31       }
    32     },
    33     mounted () {
    34       console.log('mixin mounted')
    35     },
    36     methods: {
    37       toggleText () {
    38         this.text = 'mixin text'
    39       }
    40     },
    41     computed: {
    42       plusText () { // 此处需要创建函数作用域以使this指向Vue实例
    43         return '+ ' + this.text + ' +'
    44       }
    45     },
    46     filters: { // 选项过滤器
    47       supplyUpper: value => value.toUpperCase()
    48     },
    49     watch: { // 监听器
    50       text (value) {
    51         console.log('mixin text: ' + value)
    52       }
    53     }
    54   }
    55   let vm = new Vue({
    56     el: '#app',
    57     mixins: [ mixin ],
    58     data () {
    59       return {
    60         title: 'A Title',
    61         text: 'which one?'
    62       }
    63     },
    64     mounted () {
    65       console.log('instance mounted')
    66     },
    67     methods: {
    68       toggleText () {
    69         this.text = 'instance text'
    70       }
    71     },
    72     watch: {
    73       text (value) {
    74         console.log('instance text: ' + value)
    75       }
    76     }
    77   })
    78 </script>
    79 </body>
    80 </html>
    View Code

    总结

      今天学习的还好,就是对render 那里卡了一下午

      有过一次做轮播图的经验,但是感觉这些东西 在实际项目的时候还是会用笨方法来操作

      看后续实战项目的学习了

    Let it roll
  • 相关阅读:
    移动端支付6位密码框
    移动端canvas刮刮乐
    原生ajax请求json数据
    canvas绘制video
    移动端阻止默认长按选中文本和弹出菜单、点击阴影
    前端移动端相关的代码(pc端与移动端自动切换)
    统一管理网站中的某些需要定期更新的时间届数 倒计时 ( 换届 之类的网站)( 兼容ie )
    Hbuilder 常用快捷键汇总
    文件找不到,路径错误问题
    图片清晰度问题
  • 原文地址:https://www.cnblogs.com/WaterMealone/p/14353773.html
Copyright © 2011-2022 走看看