vue入门

vue渐进式框架:

渐进式意味着你可以将Vue作为应用的一部分嵌入其中,带来更丰富的交互体验。或者如果希望将更多的业务逻辑使用Vue实现,那么Vue的核心库以及其生态系统。比如Core+Vue-router÷ Vuex,也可以满足各种各样的需求。

 

MVVM:

 

 

 

1、数据与界面分离

<div id='app'>
        <h2>{{message}}</h2>
    </div>

    <ul id='app2'>
        <li v-for='item in datas'>{{item}}</li>
    </ul>

    <script>
        let app = new Vue({ //options
            el: '#app', //挂载绑定元素
            data: { //绑定数据,实时更新,响应式,更有利于更新从服务器获取的数据
                message: 'hello'
            }
        })

        let app2 = new Vue({
            el: 'ul',
            data: {
                datas: [1, 2, 3]   //服务器增删数据,自动修改
            }
        })

 data需要说明一下:组件的高复用性导致其可能在多个页面使用,需要将data相互隔离,一般组件内的data需要作为函数return包装,为了防止污染全局。若为对象的data,不包裹,会造成全局污染

 

2、生命周期:诞生到消亡的整个过程,与其中间各个阶段的操作(可以提取其回调函数执行一系列操作)(钩子函数)

              

 

 3、基本语法:

  3.1:插值(文本赋值):mustache(双大括号)、v-once、v-html、v-text(不常用)、v-pre、v-cloak

 <!-- v-cloak:vue解析前与解析后 -->
    <div id='app' v-cloak>   
        <!-- mustache -->
        <h2 v-once>{{message + loc}}</h2>
        <h2>{{num*2}}</h2>
        <h2 v-html='url'></h2>
        <h2 v-text='message'></h2>
        <h2 v-pre>{{message + loc}}</h2>
        <h2>{{message + loc}}</h2>
    </div>

    <script>
        let app = new Vue({ //options
            el: '#app', //挂载绑定元素
            data: { //绑定数据,实时更新,响应式,更有利于更新从服务器获取的数据
                message: 'hello',
                loc: 'world',
                num: 100,
                url:'<a href="http://www.baidu.com">百度一下</a>'
            }
        })

 

  3.2:动态绑定(属性赋值)。v-bind(语法糖

    <div id='app'>
        <!-- v-bind给属性绑定获取的数据 -->
        <img v-bind:src="img" alt="">
        <!-- :为其语法糖 -->
        <a v-bind:href="url">百度一下</a>
    </div>

    <script>
        let app = new Vue({
            el: '#app',
            data: {
                img: 'http://bpic.588ku.com/element_origin_min_pic/16/10/29/2ac8e99273bc079e40a8dc079ca11b1f.jpg',
                url: 'www.baidu.com'
            }
        })

    3.2.1:v-bind绑定class,可以另外定义其他class,最后会合并

        使用对象语法,class内以键值对出现,末尾为boolean:   {key: value}

        使用数组语法,用得比较少,因为不能定状态,何不将其放在别的class内

    <div id='app'>
        <a :href="url" class="title" :class="{red:isRed,black:isBlack}">百度一下</a>
        <a :href="url" class="title" :class="getColor()">百度一下</a>
        <button v-on:click='turnColor'>变色</button>
    </div>

    <script>
        let app = new Vue({
            el: '#app',
            data: {
                url: 'www.baidu.com',
                isRed: true,
                isBlack: false
            },
            methods: {
                turnColor: function () {
                    //取反即可
                    this.isRed = !this.isRed,
                        this.isBlack = !this.isBlack
                },
                getColor: function () {
                    return {
                        red: this.isRed,
                        black: this.isBlack
                    }
                }
            }
        })

    3.2.2:v-bind绑定style。也是对象语法、数组语法

    <div id='app'>
        <h2 :style="{color:'red',fontSize:'15px'}">hello</h2>
        <h2 :style="{color:'red',fontSize:finalSize}">hello</h2>
        <h2 :style="getStyle()">hello</h2>
        <h2 :style="[baseStyle]">hello</h2>
    </div>

    <script>
        let app = new Vue({
            el: '#app',
            data: {
                finalSize: "50px",
                baseStyle: {
                    color: 'red',
                    fontSize: '50px'
                }
            },
            methods: {
                getStyle: function () {
                    return {
                        color: 'red',
                        fontSize: this.finalSize
                    }
                },
            }
        })

 

    3.2.3:计算属性(也可以理解为methods的语法糖,但是比methods高效),主要是为了展示某些数据,让其名称更明确,更利于理解

    <div id='app'>
        <h2>{{message+loc}}</h2>
        <h2>{{getMsg()}}</h2>
        <h2>{{Msg}}</h2>
    </div>

    <script>
        let app = new Vue({ //options
            el: '#app', //挂载绑定元素
            data: { //绑定数据,实时更新,响应式,更有利于更新从服务器获取的数据
                message: 'hello',
                loc: 'world'
            },
            methods: {
                getMsg: function () {
                    return this.message + this.loc
                }
            }, 
            computed: {
                Msg: function () {
                    return this.message + this.loc
                }
            }
        })

   计算属性的本质是getter和setter,所以完整的计算属性应该为

                Msg2:{
                    //一般来说set不需要实现,计算属性主要为只读属性,不可写,所以一般省略set,再简写,即为上面的Msg
                    set: function(){

                    },
                    get: function(){
                        return this.message + this.loc
                    }
                },

  计算属性和methods的本质区别:缓存。若要做重复操作,使用methods会重复调用,而计算属性会缓存计算内容,只执行一次

 

    3.2.4:事件监听:v-on(语法糖@)

      v-on参数传递:如果不传参,可以不写小括号;如果要默认传事件参数,在调用时实参不加括号,但是在执行代码内形参为e;如果需要传参,还需要事件,则$event,不可简写,必须是$event

  <div id='app'>
    <button @click=onClick>点击</button>     //不加参数
    <button @click=onClick2(10,$event)>点击</button>
  </div>

  <script>
    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      methods: {
        onClick(e) {
          console.log(e);
        },
        onClick2(a,e){
          console.log(a,e);
        }
      }
    })

      v-on修饰

      .stop-调用event.stopPropagation(),停止冒泡;.prevent-调用event.preventDefault(),阻止默认行为;;.native -监听组件根元素的原生事件;.once -只触发一次回调;.capture事件捕获;.self自身内部;.passive立刻触发,比如配合scroll使用的时候,不必等到scroll完成才调用,可以大幅度提高移动端的性能。

  <div id='app'>
    <div @click=divClick>
      <!-- stop阻止冒泡 -->
      <button @click.stop=onClick>点击</button>
    </div>

    <form action="baidu.com">
      <!-- prevent阻止默认行为,如submit的跳转 -->
      <input type="submit" name="" id="" @click.prevent='submitClick' value="提交">
    </form>
  </div>

  <script>
    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      methods: {
        onClick(e) {
          console.log(e);
        },
        divClick() {
          console.log('盒子被点击了');
        },
        submitClick() {
          console.log('点击提交');
        }
      }
    })

    使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击 

 

    3.2.5:条件判断v-if、v-else-if、v-else,vue中可以根据值的状态在dom中渲染或销毁(不出现该标签)元素或组件。可以作为判断显示

  <div id='app'>
    <h2 v-if='score>90'>优秀</h2>
    <h2 v-if='score>80'>良好</h2>
    <h2 v-if='score>60'>及格</h2>
  </div>

  <script>
    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      data: {
        score: 70,
      }
    })

    

    3.2.6:v-show,是否渲染。与v-if的区别:如果false,v-if下dom中不存在该元素,而v-show只是将其display设为none,不占位。所以当需要频繁切换时,使用v-show,一次切换可用v-if。

      注意:v-show不支持 <template> 元素,也不支持 v-else

 

    3.2.7:循环:v-for,主要用来遍历数组。如果需要索引  v-for=(item,index) in item。index即为原数组索引。使用v-for时,最好给对应的元素或组件添加上key属性,主要是为了高效的更新虚拟dom。vue内的虚拟dom和diff算法

  <div id='app'>
    <ul>
      <li v-for='item in movie' :key='item'>{{item}}</li>      //有key时,优先对应内容,提高插入等操作的效率,这里的key值有要求,不能随便写index,应该用唯一标识,item或者id
      <li v-for='(item,index) in movie'>{{index}}.{{item}}</li>          //索引与数
      <li v-for='item in info'>{{item}}</li>         //遍历,输出各个值
      <li v-for='(value,key,index) in info'>{{index}}.{{key}}.{{value}}</li>   //索引,键值
    </ul>
  </div>

  <script>
    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      data: {
        movie: ['银河', '异形'],
        info: {
          id: 1,
          name: 'jacky'
        }
      }
    })

    如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

 

    3.2.8:检测数组更新。由于vue是响应式,所以以下数组操作会触发视图更新push()添加到最后,pop()删除最后一个,shift()删除第一个,unshift()数组最前面添加元素,splice()添加、删除、替换,sort()排序,reverse()翻转,set()修改值。有的不会触发更新,比如直接根据下标替换内容:this.arr[0] = 修改后的值,不会更新

 

     3.2.9:v-model表单绑定:在input / textarea/select内绑定属性,实现与data的双向绑定:data内容修改,input其值修改;input其值修改,data内容修改

        区别于一般的单向响应式,如mustache,或者input的v-bind:value

       双向绑定v-model思路:首先view获取data用value等v-bind方式显示,然后再添加事件,如v-on等event事件获取输入内容,改变data数据

  <div id='app'>
    <!-- <input type="text" v-model='message'> -->
    <input type="text" :value='message' v-on:input='valueChange'>
    <!-- <input type="text" :value='message' @input = '$event.target.value'> -->
    <p>{{message}}</p>
  </div>

  <script>
    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      data:{
        message: '你好'
      },
      methods: {
        valueChange(event){
          this.message = event.target.value
        }
      }
    })

      其他的如绑定radio(单选)、checkbox(复选,多个值可以放在一个数组里)、select等输入值

      v-model修饰:lazy(相当于防抖)、number(类型改成number型)、trim(去除左右空格)

      v-model本质只是个语法糖,监听用户输入通过响应式更新数据,这里的数据指的是Vue实例的数据,也就是data,会忽略表单的value、checked、selected等初始值

 

     3.2.10:值绑定:当所需要选择的内容不确定个数时,v-for遍历动态数组,不需要写死。其实就循环遍历后再绑定值给input

  <div  id="app"> 
     <label v-for='item in oHobbies' >
      <input type="checkbox" :value='item' v-model='hobbies'>{{item}}</br>
    </label>
    <p>{{hobbies}}</p>
  </div>

  <script>
    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      data: {
        hobbies: [],
        oHobbies: ['篮球', '乒乓球', '羽毛球', '足球']
      },
    })

    3.2.11:v-once、v-html 

 

 

4、组件化:将一个页面拆分成一个个小功能模块,每个块完成属于自己的部分独立功能,便于后期管理维护

   在vue中,可以构建独立可重复的小组件来构建应用,任何应用都会被抽象成一颗组件树

   三步骤:创建组件构造器 Vue.extend()、注册组件 Vue.component()、使用组件Vue实例

  4.1:全局组件:通过Vue.component()注册,可以在多个Vue实例内使用,

     局部组件:在指定Vue实例内注册使用

  <div id='app'>
    <mycpn></mycpn>
  </div>

  <script>
    const cpnConstructor = Vue.extend({
      template: `<div>
        <p>hello</p>
        </div>`
    })

    //全局组件,意味着可以在多个Vue实例中使用
    // Vue.component('my-cpn', cpnConstrucstor)

    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      components: {
        //cpn使用组件时的标签名
        mycpn: cpnConstructor
      }
    })

    4.2:父子组件:包含关系,在父组件内注册子组件,并在template引入

    const cpnC1 = Vue.extend({
      template: `<div>
        <p>hello1</p>
        </div>`
    })

    const cpnC2 = Vue.extend({
      template: `<div>
        <p>hello2</p>
        <cpn1></cpn1>
        </div>`,
      components: {
        cpn1: cpnC1
      }
    })

    const app = new Vue({ //options
      el: '#app', //挂载绑定元素
      components: {
        cpn2: cpnC2
      }
    })

    4.3:语法糖(推荐用法)把extend的内容放在注册Vue.component内

  <div id='app'>
    <cpn1></cpn1>
    <cpn2></cpn2>
  </div>

  <script>
    //全局组件语法糖
    Vue.component('cpn1', {
      template: `<div>
        <p>hello1</p>
        </div>`
    })

    const app = new Vue({
      el: '#app',
      //局部组件语法糖
      components: {
        cpn2: {
          template: `<div>
        <p>hello2</p>
        </div>`
        }
      }
    })

    4.4:模版分离:将模版写入<script type='text/x-template' id='cpn'></script> / <template id='cpn'></template>标签内

    4.5:组件访问Vue实例对象数据:组件内创建data函数,而不是data对象,可以返回一个对象:必须是一个函数是因为让Vue每个组件对象都范湖一个新的对象,如果是同一个对象,组件在多次使用后会出现问题。举个例子,计数器组件内的counter,如果不是返回新对象,当我创建三个计数器时会共享这个counter,导致三个一起++或者--,连锁反应

    Vue.component('cpn1', {
      template: `
        <div>
          <p>{{title}}</p>
        </div>`,
      //组件内放置data,但是这个data是函数,不是对象
      data() {
        return {
          title: 'abc'
        }
      }
    })

    4.6:父子组件通讯:大组件进行网络请求,获取全部数据后将部分数据传递给小组件

      4.6.1:通过props,夫向子组件传递数据:props数组形式、对象形式(可以做类型验证),props为单向下行绑定,不能往上传,防止数据混乱。每次父级数据变化,props传下去的子也会变化

      4.6.2:通过事件,子向父组件发送消息:子组件$emit('方法',参数)发射事件给父组件,父组件v-on监听事件

 

     4.7:父子组件访问方式:

      4.7.1:父对子:$children:返回数组,获取时需要指定数组下标,即第几个子组件,所以会有问题:真正开发的时候不知道所需要的下标是第几个,所以使用$refs

             $refs:指定子组件标签内添加 ref 值(id名),在$refs后添加其名称访问指定子组件

      4.7.2:子对直系父:$parent。但是为了避免耦合,一般不这样做    

      4.7.3:访问根组件:$root,根部Vue实例  

    4.8:非父子组件通信,Vue2.x提供中央事件总线,也就是一个中介来解决。但是这个方案不如直接使用Vuex

    4.9:插槽slot(匿名插槽):组件提高扩展性,让用户决定展示什么,比如一个底板内分为三个部分,我可以展示这三个,也可以那三个,还可以混搭,反正有三个插槽

        抽取共性,保留不同:共性抽取到组件中,不同暴露为插槽:模版指定位置暴露插槽<slot></slot>,根组件内插入需要定制内容;也可以指定默认slot,根据需要修改。

       4.9.1:具名插槽:一个模版可能有多个插槽,给每个插槽指定名称,插入的时候可以指定位置

//具名插槽
  <div id='app'>
    <cpn1><button slot="top">插槽按钮</button></cpn1>
  </div>

  <template id="cpnC1">
    <div>
      <slot name='top'>顶</slot>
      <p>------------</p>
      <slot name='bottom'>底</slot>
    </div>
  </template>

 

      4.9.2:编译作用域:父组件模版的所有东西(数据)都会在父级作用域内编译,子组件模版的所有东西(数据)都会在子级作用域内编译,调用组件显示的时候也是在父组件作用域内编译

<my-cpn v-show="isShow"></my-cpn>   //最终该子组件是可以显示的,因为是在父组件内使用

         作用域插槽:子组件的内容、数据由父组件替换插槽标签展示。简单来说就是父组件拿子组件的数据进行不同风格的展示

       4.9.3:解构插槽:将插槽内容包裹在一个拥有单个参数的函数里

  

    4.10:is

      4.10.1:动态切换组件

<component v-bind:is="currentTabComponent"></component> //currentTabComponent为组件名

      4.10.2:解析DOM模版,解除html的元素限制,比如ul只能包含li

<ul>
    <li is="your-component"></li>
</ul>

 

 

5、模块化:CommonJS、AMD、CMD、ES6的Modules

export{参数1、参数2...}   //指定导出
import * as info from './info.js'   //全导入,别名

  5.1:Vue中webpack:

    5.1.1:打包执行顺序:先本地node_modules/.bin中webpack,如果没有,再去全局找

    5.1.2:Vue使用webpack打包编译的时候注意环境配置:  

      runtime+compiler:template -> 解析成ast -> 编译成render ->再创建虚拟dom

      runtime-only:只需要用到rendercreateElement,转换成虚拟dom树,再直接生成UI,在这之前已经使用vue-template-compiler处理template。性能高,代码量少

 

  5.2:Vue组件打包成 .vue文件,分离成三个部分:template、script、style。再在main.js中引入,webpack中使用vue-lodaer,安装相应loader  

  5.3:配置分离:将基础配置设为base.config.js,生产配置和开发配置再单独设置文件,修改json文件指定新配置文件

 

6、Vue Cli:

    创建项目:1、create;2、init;3、启动配置服务器Vue UI

    配置:1、Vue UI配置;2、隐藏的配置文件@Vue下cli-service设置;3、自定义配置文件并添加

 

7、Vue router路由

  路由:决定数据包来源到目的地的路径,内部有一核心概念叫路由表,本质为一个映射表,决定了数据包的指向

  后端渲染:jsp,css+html+java

  前端渲染:前后端分离。静态资源服务器(HTML+CSS+JS) + 后端数据服务器(异步API请求数据,再渲染)

  前端路由:URL映射,改变URL,响应指定组件,页面可不整体刷新

  

  7.1:前端路由规则(改变URL页面不刷新):1、修改URL的hash(#);2、HTML5的history.pushState() / .replaceState() / .go / .forward() / .back

  7.2:Vue-router:

      使用:导入路由对象,调用Vue.use(VueRouter);创建路由实例,传入映射配置;挂载

      配置:一个组件对应一个路径。router-link引用,渲染成一个a标签;router-view渲染显示组件;路由切换是切换router-view

   7.3:router-link:

    7.3.1:to跳转、tag指定渲染成什么组件、replace不留下history、active-class可设置一个router-link-active的class,一般用来设置高亮css类

    7.3.2:代码跳转:点击或者自定义其他事件,设置方法将其 this.$router.push('/about') 或者replace 跳转,主要是可扩大事件与标签范围,不局限于a等其他标签

  7.4:动态路由:根据返回数据将URl修改,如登录后URl会在结尾加上用户名:路由内配置路径path: 'user/:id',组件内实现跳转 :to='/user/返回用户名';若组件要获取路由信息,则可在组件内定义计算属性,返回 this.$route.params.id$route不是router,拿回当前活跃route,id为路由配置内的 :id

  7.5:路由懒加载:避免将大型js包打包成一个文件,当网络拥堵时造成用户页面空白,懒加载就是将路由对应组件打包成一个个代码块,路由被访问时才加载对应组件

  7.6:嵌套路由:创建对应子组件,在路由映射中父组件路由下配置对应子路由children;再父组件内router-link指向带父组件地址的url,如 /home/msg ,再添加router-view指定显示位置

   

 

   7.7:传参:params、query

     7.7.1:params配置路由:/router/:id,通过path后面对应的值传参,获取用$route.params.name,适合简单传递

    7.7.2:query普通配置:/router/?id=query,query的key传参,获取也是用 $route.query.name,适合大量传递,因为传递的是对象

  7.8:导航守卫:监听路由的进入和离开,然后执行相应操作(比如切换路由浏览器标题切换)beforeEach和afterEach钩子函数:

      7.8.1:全局守卫:单个监听可以在每个组件下的created生命周期添加dom操作,如document.title,但是很麻烦,所以使用全局导航守卫:在router页面定义钩子函数,在钩子函数内执行

 

//前置钩子,跳转前回调
router.beforeEach(function (to, from, next) {
  //from从哪来(即将离开的路由),to到哪去(跳转到的路由),各个路由配置内配置meta元数据(描述数据的数据)
  document.title = to.meta.title
  //必须执行下一步,可以是跳转下一个钩子,也可以执行别的操作
  next()
})

//后置钩子,跳转后回调,不需要next
router.afterEach()

 

      7.8.2:路由独享守卫:在配置路由的时候内部配置钩子函数beforeEnter等,和全局守卫类似

      7.8.3:还有组件守卫等

  7.9:keep-alive:Vue内置的组件,可以将包含的组件保留其状态,避免重新渲染,include属性,匹配的组件会被缓存;exclude属性,匹配的组件不会被缓存

      router-view如果被包含在keep-alive里,所有路径匹配到的视图组件都会被缓存。keep-alive定义在根App.vue内才生效,因为属性include需要查询各个组件的name

 

8、Vex:状态管理模式,集中式存储管理,其实就是将多个组件(多个页面)的共享变量放在一个对象里,并将其放置于顶层Vue实力内,让其他组件可访问。Vuex最大特点:响应式:

   8.1:单页面管理:

 

  8.2:Vuex管理:按照规则执行,不可绕过,绕过的话devtools无法跟踪(如,组件不可直接改变state)

 

   8.3:Vuex核心:State、Getter、Mutation、Action、Module

    8.3.1:State单一状态树(单一数据源) ,方便管理,维护,为了安全

    8.3.2:Getters,类似计算属性,只是把计算属性公用了。getters不能随便传参,自定义传参的话可以返回一个函数,让函数传参。在组件中可以使用mapGetters映射,将所需要的getters结构传入

    8.3.3:Mutation,用来更新state的唯一方式(更新时,需要调用commit方法才能更新)。包含事件类型和回调函数。

       Mutation响应式规则:1、如果是对象,提前在store内初始化好所需属性;2、如果要添加新属性,必须使用Vue.set(obj, 属性名, 值),或者用新对象重新赋值。这样才可以响应式,否则view视图不会刷新

    mut(state) {
      //非响应式,该方法也不在数组响应式方法内
      // state.students2['age'] = 18
      // delete state.students2.id  
      //set在
      Vue.set(state.students2, 'age', 18)
      Vue.delete(state.students2, 'id')
      //或者赋予新对象
      state.students2={
        ...state.students2,'age':18
      }
    }

      Mutation的常量类型:将方法名设置为常亮,将其放于一个映射文件内,便于后期维护

    8.3.4:Action:Mutation的devtools监控同步函数,异步使用action(调用dispatch更新)。注意:该处可以理解为增加了一个环节,修改属性必须还是通过mutation,而不能将action替代掉mutation而直接在action内修改state属性,理解Vuex流程图。因为是异步,所以可以考虑promise,灵活使用then执行函数:比如提交成功或失败用Promise回馈。同理actions也可以用映射mapActions

//index.js
  actions: {
    //context可理解为store
    acUpdateStu(context) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          context.commit('mut')
          resolve('成功')
          reject('失败')
        }, 1000)
      })
      //以下的then也可以在客户端内函数执行,让用户决定promise内容
      // }).then(res=>console.log(res)).catch(rej=>console.log(rej))
    }
  },

//App.vue
muts() {
      this.$store
        .dispatch("acUpdateStu")
        .then((res) => console.log(res))
        .catch((rej) => console.log(rej));
    },

    8.3.5:Module:将store分割成多个模块,每个模块都有store的内容,如state,actions等。

      Modules内的异步action调用根属性的时候可以使用rootState,rootGetters等,这些都包含在context内

    8.3.6:项目结构:

 

 9、关于事件总线:

  Vue2.x中new一个eventBus

  Vue3中,事件总线模式可以被替换为使用外部的、实现了事件触发器接口的库,例如 mitt 或 tiny-emitter

  但是不鼓励使用,短期可以解决问题,但是长期来看不利于维护,有如下替代方案:

  1、prop逐级穿透传递父子组件通讯,但是有时候远距离通信过于麻烦,会在某些组件中传递不必要的prop

  2、provide和inject,可以远距离通信

  3、Vuex

 

10、Mixin混入(部分转载https://www.cnblogs.com/dengyao-blogs/p/11589962.html)

  混入也是一个封装,封装的是Vue组件的生命周期所要执行的函数。引入mixin分局部引用和全局引用

  创建了混入对象之后,我们自定义的方法或者变量可以很轻松的挂载在Vue实例上

     1、mixin混入对象的变量是不会共享的,多个组件引用,一个发生了变化,并不会通知mixin进行实时刷新数据,发生的变化只会在page1.vue中生效,不影响其他组件

    2、如果是同名钩子函数将合并为一个数组,因此都被调用,但是混入对象的钩子将在自身实例钩子之前触发

    3、值为对象的选项,例如methods,components等如果变量名和mixin混入对象的变量名发生冲突,将会以组件优先并进行递归合并,相当于组件数据直接覆盖了mixin中的同名数据;

    4、若想自定义合并:Vue.config.optionMergeStrategies

    5、全局引用会影响所有组件的使用,在名称定义需要注意

  和Vuex的区别:Vuex是状态共享管理,所以Vuex中的所有变量和方法都是可以读取和更改并相互影响的;mixin可以定义公用的变量或方法,但是mixin中的数据是不共享的,也就是每个组件中的mixin实例都是不一样的,都是单独存在的个体,不存在相互影响的;

      

12、$nextTick

  mounted是DOM渲染完毕,但是不代表图片等资源渲染完毕。

  如要等图片等渲染完毕再操作,可以使用$nextTick等下一次DOM更新循环结束后延迟回调,比如数据修改后、图片加载完毕后立即执行等操作。

  $nextTick所放置的位置需要注意,要确定所放位置的下一帧是否满足要求,比如放在图片加载完成之后,DOM刷新

 

上面为codewhy视频总结。以下为自行阅读Vue官方文档后补充的内容:

13、Vue2.6之后的动态参数

  2.6之后添加了动态参数,可以动态的改变标签参数

//attributeName可以是href,或者别的
<a v-bind:[attributeName]="url"> ... </a>
//eventName可以是focus
<a v-on:[eventName]="doSomething"> ... </a>

  动态参数预期会求出一个字符串,异常情况下值为 null。这个特殊的 null 值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。

 

14、有关key:

  Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。但有时候会带来问题:比如两个input切换的时候,一个input的内容可能会复用到另一个input上,而我们是想切换的时候换成一个空的input。如果不需要复用,则在input上绑定一个唯一key

 

15、Vue组件处理边界情况:

  15.1:访问根实例:$root

  15.2:访问父级组件实例:$parent

  15.3:访问子组件ref:$refs只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——应该避免在模板或计算属性中访问$refs

  15.4:依赖注入:当子组件需要访问父组件的方法时,父组件可以provide将方法/函数提供出去

provide() {
  return {
    getMap: this.getMap
  }
}

    子组件使用inject接收

inject: ['getMap']

    可以将其认为是一个更大范围的prop

  15.5:程序化的事件侦听器:比如执行一次的函数,利用once自动清理

  • 通过 $on(eventName, eventHandler) 侦听一个事件
  • 通过 $once(eventName, eventHandler) 一次性侦听一个事件
  • 通过 $off(eventName, eventHandler) 停止侦听一个事件

  15.6:组件循环套用:A中有B,B中有A(这样会造成一个问题,Vue不知道怎么不经过一个引用另一个):beforeCreate创建;webpack异步import

 

16、过渡&动画(单纯举例,详细的可到Vue官网查看文档 https://cn.vuejs.org/v2/guide/transitions.html

  16.1:transition过渡

  <transition name="fade">
    <p v-if="show">hello</p>
  </transition>

    属性name和追加的类名一致:.fade-enter-active, .fade-leave-active等

  16.2:css过渡:和transiton类似,也是name上设置如slide,css内定义slide属性

  <transition name="slide-fade">
    <p v-if="show">hello</p>
  </transition>

    name都是自定义的

  16.3:JS的钩子函数:before-enter等,在过渡生命周期期间执行相应操作

 

17、自定义指令

   全局:

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

  局部:

directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

  相关钩子函数:bind、inserted、update、componentUpdated、unbind

  • bind():当指令绑定在 HTML 元素上时触发

  • inserted():当指令绑定的元素插入到父节点中的时候触发

  • update():当指令绑定的元素状态/样式、内容(这里指元素绑定的 vue 数据) 发生改变时触发

  • componentUpdated():当 update() 执行完毕之后触发

  • unbind():当指令绑定的元素从 dom 中删除时触发

 

18、渲染函数render和JSX

   18.1、render渲染元素,有时候比创建组件来得方便,比如根据type来展示不同的 h级标签

//组件
<script type="text/x-template" id="anchored-heading-template">
  <h1 v-if="level === 1">
    <slot></slot>
  </h1>
  <h2 v-else-if="level === 2">
    <slot></slot>
  </h2>
  <h3 v-else-if="level === 3">
    <slot></slot>
  </h3>
................
props: {
    level: {
      type: Number,
      required: true
    }
  }


//render函数
  render: function (createElement) {
    return createElement(
      'h' + this.level,   // 标签名称
      this.$slots.default // 子节点数组
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }

  18.2、虚拟DOM:createElement => createNodeDescription,VNode即虚拟dom节点

  18.3、注意,深入底层自定义指令后,v-model、v-if等就无法使用,只能使用原生自己实现这些功能

  18.4:JSX:Babel插件,javascript+xml,直接return一个html模版,减少书写量,更直观

  18.5:函数式组件(将functional设置为true):定义那些没有响应数据,也不需要有任何生命周期的场景,它只接受一些props 来显示组件

 

19、插件:

  1. 添加全局方法或者 property。如:vue-custom-element

  2. 添加全局资源:指令/过滤器/过渡等。如 vue-touch

  3. 通过全局混入来添加一些组件选项。如 vue-router

  4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

  5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router

 

vue的注意事项:

1、由于vue采用虚拟dom,会造成一个复用的情况,在某些条件下,如多个input,当切换的时候,虚拟dom会复用前一个dom,会造成dom内value不清空,此时可以创建一个key,让vue区分哪些需要复用,哪些不需要复用。

<div id="app">
  <span v-if="isUser">
    <label for="username">用户账号</label>
    <input type="text" id="username" placeholder="用户账号" key="username">
  </span>
  <span v-else>
    <label for="email">用户邮箱</label>
    <input type="text" id="email" placeholder="用户邮箱" key="email">
  </span>
  <button @click="isUser = !isUser">切换类型</button>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      isUser: true
    }
  })

2、过滤器(vue3移除,使用计算属性),格式化通用文本

3、驼峰:在component的props内,用驼峰的话,template就要换成相应的驼峰,否则不能识别。但是在实例下HTML标签内的传输v-bind要换成-连接,不能也用驼峰,不然会报错

  <div id='app'>
    <cpn1 :c-msg='msg'></cpn1>
  </div>

  <script>
    const app = new Vue({
      el: '#app', 
      data: {
        msg: 'hello',
      },
      components: {
        cpn1: {
          template: `
          <div>
            <p>{{cMsg}}</p>
          </div>`,
          props: {
            //此处用驼峰的话,上面的template就要换成相应的驼峰,否则不能识别。但是在实例下HTML标签内的传输v-bind要换成-连接,不能也用驼峰,不然会报错
            cMsg: String
          }
        }
      }
    })

 4、Vue2.6后slot和slot-scope统一为v-slot,语法糖为#

5、Vue原生开发不包含webpack,命名时需要注意大小写问题

6、Vue与webpack打包编译的时候注意运行环境配置版本:compiler和runtime。打包前指定webpack配置环境

//在webpack.config.js中
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }

  不过后期使用手脚架不需要配置那么多

 7、当打开首页的时候,默认没有显示首页的组件,需要用户点击,体验不好。这时可以让路径默认跳转默认路由:新建一个映射,将 '/' redirect到主页,如 '/home' 上

const routes = [{
    path: '/',
    redirect: '/home'
  }]

8、关于路由懒加载:不可以在路由配置上直接import组件,否则其不会执行懒加载,需要指定,ES6写法:

 component: () => import('../views/About.vue')

还有别的如AMD写法

9、使用插槽的时候,尽量外面再包一层其他标签如div,一些判断,如是否展示 v-if 等写在该标签内,而不写在插槽内,防止插槽被替换而不起效果

10、别名:cli4下起别名需要手动创建vue.config.js,重新run后再使用别名。在属性内的位置需要在别名前加 ~ ,import可不加

11、获取组件元素,首先在父组件上给子组件定义ref,然后引用的时候使用 this.$refs.子组件ref名称.$el.方法,如 offsetTop

 12、要理解Vue的核心,数据响应的原理,当修改props值的时候,其实父的本值也被改变了,导致其他使用该值的组件内的值也改变了

13、利用Vue.use自定义插件,如toast

 14、当v-for和v-if同时出现时,Vue2优先处理v-for,Vue3优先处理v-if,但是建议永远不要两个放在一起用,讲要判断的值换做计算属性返回后在v-for

15、$listeners:当子组件为一个被包装过的input子组件,.native不能如期生效,可以在子组件上使用该对象,将事件监听指向某个特定元素

16、router-linl的exact-active-class,当组件被激活时,默认加上该类,可配置精准匹配激活类,就不用在多个router-link上添加v-if判断再添加类了

exact-active-class="active"  //只有一个router-link会被激活

当然,也有模糊匹配,适合配置父子路由,都需要激活某类的时候

active-class="active"  //父子同体系下可能会有多个router-link会被激活

 Vue3需要注意模糊匹配:路由路径包含 且 需要有路由嵌套关系,才可模糊激活

       {
        path: "/member",
        component: MemberLayout,
        children:[
          {
            path: "/member",
            component: MemberHome,
          },{
            path: "/member/order",
            component: MemberOrder,
          },
          {
            path: "/member/order/:id",
            component: MemberOrderDetail,
          },
        ]
      },


 /member 和/member/other   不是嵌套路由,不会加上这个类 router-link-active

 修改:

          {
            path: '/member/order/',
            // vue3.0 需要有嵌套关系才能模糊匹配    
            component: { render: () => h(<RouterView/>) },
            children: [
              { path: '', component: MemberOrder },
              { path: ':id', component: MemberOrderDetail }
            ]
          }

 

posted @ 2021-09-29 15:32  Jacky02  阅读(98)  评论(0)    收藏  举报