美文网首页
Vue.js(Vue2)学习笔记

Vue.js(Vue2)学习笔记

作者: 甜柚小仙女 | 来源:发表于2022-01-21 16:38 被阅读0次

    一、创建Vue实例

    1.创建
    实例property和方法

    var vm = new Vue({
       // 选项
       el: '#app',
       data: obj,
       created: function(){} // 生命周期钩子
    })
    // 可以使用$访问vue实例property和方法:vm.$data  、vm.$el 
    

    2. 生命周期
    beforeCreate->
    created->
    beforeMount->
    mounted->
    beforeUpdate->
    updated->
    beforeDestory->
    destroyed

    二、模版语法

    • 双大括号-“Mustache”语法: {{变量}}
    • v-once:一次性插值,数据改变,插值内容不更新<span v-once>
    • v-html:输出真正的html,替换元素的innerHTML<span v-html>
    • v-bind:[attr] 或者 :[attr]: 绑定attribute;attr可以是动态参数值或者是表达式
    • v-on:[eventName][.modifier(修饰符)]或者@[eventName]:监听DOM事件;eventName可以是动态参数值或者是表达式。
    • 指令:带有v-前缀的特殊attriibute

    三、计算属性和侦听器

    1. 计算属性:

    • 使用:vm.comProperty
    • 定义
    computed: {
       comProperty1: function(){}
    }
    
    • 默认只有getter,可以自己提供一个自定义setter
    • 特点:基于响应式依赖进行缓存,依赖发生改变时重新求值
    • VS 方法:触发重新渲染,方法会重新执行函数
    • VS 侦听属性watch:计算属性直接拿到依赖动态变量的新的计算结果;侦听属性监听动态变化的变量或者函数的计算结果,从而做一些事情。

    2. 侦听器:

    • 使用:
     watch: {
        variable: function(newVal, oldVal){}
     }
    
    • 作用:当某些数据变化时,需要执行异步或者开销比较大的操作

    四、Class与Style绑定

    1、class绑定

    • 使用:
    1. v-bind:class="{active: isActive}" 或者 v-bind:class="classObject" 
    2. v-bind:class="[isActive ? cl1 : '', cl2]" 或者 v-bind:class="[{cl1: isActive}, cl2]"
       data:{
         cl1:'active',
         cl2:'danger'
       }
    
    • 可以和普通class共存

    2、style绑定

    • 使用:
    1. v-bind:style="{display: activeDisplay}" 或者 v-bind:style="{styleObject}" 
    data: {
      activeDisplay: ['-webkit-box', '-ms-flexbox', 'flex'] // 只会渲染数组中最后一个被浏览器支持的值
    }
    2. v-bind:style="[baseStyles, overrideStyles]"
    
    • vue会自动侦测并添加css对应的浏览器引擎前缀

    五、条件渲染

    1、v-if

    • 使用:v-if、v-else-if、 v-else
    • 使用key标记元素是独立的,不复用
    • 特点:惰性渲染,条件为假,则不渲染,所以切换开销大。运行时条件很少变,用v-if比较好、
    • 不要将v-if和v-for放在同一个元素上:v-for比v-if优先级更高

    2、v-show

    • 使用:v-show
    • 特点:元素始终会被渲染,通过css切换显隐,所以初始渲染开销大,但是切换开销小。

    六、列表渲染

    1、使用:

    1. v-for="(item, index) in items" 或者 v-for="item of items" // items是一个数组
    2. v-for="(val,name,index) in obj" // obj 是一个对象。按照Object.key()的结果遍历
    3. v-for="i in 10" // 遍历1-10
    4.// 在组件中使用v-for,使用v-bind将item作为props注入组件内部
    <my-component
      v-for="(item, index) in items"
      v-bind:item="item"
      v-bind:index="index"
      v-bind:key="item.id"
    ></my-component>
    

    2、维护状态
    列表更新时,如果顺序改变,vue默认不移动元素来匹配顺序。所以应该提供一个唯一的key(数值或字符串)来标记每个节点的身份,从而重用和重新排序现有的元素。
    3、数值变更检测
    数组方法中改变原数组的方法都会触发视图更新;不会改变原数组只会返回新数组的方法不会触发视图更新,但是可以使用新生成的数组替换掉旧数组
    4、注意

    • 数组的改变不是通过数组方法的情况,vue不能检测到数组和对象的变化(由于数组和对象的地址没有改变)
    • 在组件中使用v-for,key是必须的

    七、事件处理

    1、使用:

    1. v-on:click="counter+=1" 或者 v-on:click="handleClick"
    2. v-on:click="handleClick('hello',$event)" //在js中直接调用方法
    

    八、表单输入绑定

    1、使用

    1. v-model[.modifier]="inputVal"  // 在表单元素上创建双向数据绑定。他会根据空间类型自动选取正确的方法更新元素。
    

    2、工作原理
    监听用户输入事件使用元素对应的property更新v-modal绑定的表单值。

    • text、textarea 监听input事件,使用value更新
    • checkbox、radio监听change事件,使用checked更新
    • select监听change事件,使用value更新

    3、注意
    v-model会忽略元素的value、checked、selected初始值,所以应该通过data选项声明初始值。

    九、组件注册

    组件命名:1.首字母大写(大驼峰命名法) 2.短横线分隔命名kebab-case
    1、 全局注册

    Vue.component('my-componenta(组件名)',{
    // 选项(除了el,其他根实例的选项都可以用)
      data: function() {
         return {
           a:1
         }
      } // data必须是一个函数
    })
    
    new Vue({
    el:'#app'
    })
    
    <div id="app">
    <my-componenta></my-componenta>
    </div>
    

    2、局部注册

    var ComponentA = {name:'',...}
    new Vue({
    el:'#app',
    components:{'component-a':ComponentA}
    })
    

    3、局部注册的组件在其子组件中不可用
    如果希望局部注册的组件在子组件中可用,需要这样写:

    var ComponentA = {...};
    var ComponentB = {
    components:{
      'component-a':ComponentA
      }
    }
    
    或者:
    import ComponentA from './ComponentA.vue'
    
    export default{
    components:{
      ComponentA
      }
    }
    

    在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:

    • 用在模板中的自定义元素的名称
    • 包含了这个组件选项的变量名

    4、注意

    • 在DOM中使用组件时,只有kebab-case是有效的
    • 组件可以任意复用,每个组件维护自己的状态,每用一个组件,就会创建一个新实例。
    • 每个组件必须只有一个根元素

    十、Prop

    1、大小写

    • 使用DOM模板时,因为html大小写不敏感,所以父组件html中的props名应该是kebab-case的,子组件在js中接收的时候可以是驼峰命名的
    • 字符串模板没有这个限制

    2、父组件传递prop

    v-bind:title="post.title"
    v-bind:post="post"
    v-bind="post" // 传递一个对象的所有property
    

    3、子组件接收prop

    props: {
      title: String
    }
    this.title // 访问
    

    4、单向数据流:

    • 父子prop之间形成单向下行绑定:父级prop的更新会向下流动到子组件,但反过来不行。所以prop不可修改,防止子组件意外改变父组件状态(prop是引用类型时),导致应用数据流向难以理解。

    5、prop验证

    Vue.component({
      props:{
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        propA:Number,
    // 多个可能的类型
        propB:[String,Number],
    //必填的字符串
        propC: {
            type: String/Number/Object,
            required: true,
            default: function () {
              return { message: 'hello' }
            },
            // default: 100,
            validator: function (value) {
               // 这个值必须匹配下列字符串中的一个
               return ['success', 'warning', 'danger'].indexOf(value) !== -1
            }
        }
      }
    })
    

    十一、自定义事件

    1、命名
    事件用kebab-case命名
    2、使用

    //监听事件
    v-on:my-event = "n += $event"
    //或者
    v-on:my-event = "myEvent"
    methods: {
      myEvent: function (arg) {
        this.n += arg
      }
    }
    //触发事件
    this.$emit('my-event', 1)
    
    

    3、将原生事件绑定在组件上

    • 使用native修饰符(局限:如果组件根元素不是表单元素,没有你监听的事件则会监听失败)
    • 使用$listeners 属性

    4、.sync修饰符

    1. 子组件通过事件来修改父组件的property的情况,推荐以update:myProperName的模式触发事件
    this.$emit('update:title',newTitle)
    
    <my-com v-bind:title="doc.myTitle" v-on:update:title="doc.myTitle = $event"></my-com>
    // 为了方便起见,提供一个缩写:.sync修饰符
    <my-com v-bind:title.sync="doc.myTitle" ></my-com>
    // myTitle只能是一个property名,不能是表达式
    
    //用一个对象同时设置多个prop,doc只能是一个property名,不能是一个字面量对象
    <my-com v-bind.sync="doc" ></my-com>
    

    十二、插槽

    v-slot取代了slot、slot-scope这两个attribute
    1、普通插槽

    • 使用:
    <my-component>abc</my-component>
    
    my-component中:<a><slot>当父组件不提供插槽内容的时候显示</slot></a>
    
    渲染结果: <a>abc</a>
    
    • 编译作用域
      父级模板的所有内容都是在父级作用域中编译;子模板的所有内容都是在子作用域中编译的

    2、具名插槽

    • 使用:
    1.
    <my-component>
        <p>dfg</p>
        <template v-slot="head">
             <h1>12345</h1>
        </template>
    /* 废弃的语法
        <template slot="head">
             <h1>12345</h1>
        </template>
    */
        <p>678</p>
    </my-component>
    my-component中:
    <div>
       <header>
          <slot name="head"></slot>
       </header>
       <main>
          <slot></slot>  
       // 没有name默认name=“default”
       </main>
    </div>
    渲染结果:
    <div>
       <header>
          <h1>12345</h1>
       </header>
       <main>
         <p>dfg</p>
         <p>678</p>
       </main>
    </div>
    2.插槽名也可以是动态的
      <template v-slot:[dynamicSlotName]>
      </template>
    3.插槽名缩写
    (v-slot:) => (#) 
     v-slot:header 可以被重写为 #header
    ‘#’ 后面必须有参数,否则无效
    
    • 注意
      1.\color{red}{v-slot只能添加到 <template>上}。只有一种例外情况
      2.废弃的slot attribute可以添加到任意元素上,包括普通元素

    3、作用域插槽

    • 作用:让父组件的插槽内容可以访问到子组件的数据
    • 使用:
    1.在子组件的<slot>元素上绑定需要传的值,拿上述例子:
       <header>
          <slot name="head" v-bind:user="user"></slot>
       </header>
    2.在父组件插槽中使用v-slot定义子组件提供的插槽prop的名字并使用
       <template v-slot:head="slotProps">
           <h1>12345</h1>
           {{slotProps.user.xxx}}
       </template>
      /*废弃语法
      <template slot="head" slot-scope="slotProps">
        {{ slotProps.msg }}
      </template>
    */
     //  默认插槽需要用在组件标签上。不带参数的被指定为对应默认插槽相当于v-slot:default="slotProps" 
       <my-component v-slot="slotProps">
         <p>dfg</p>
         <p>{{slotProps.user.xxx}}</p>
       </my-component>
    3.插槽prop可以解构、重命名,也可以定义默认值
     v-slot="{ user: person }"  // 使用:{{ person.firstName }}
     v-slot="{ user = { firstName: 'Guest' } }" // 使用:{{ user.firstName }}
    
    • 注意
      1.子组件中被提供的内容只有默认插槽的时候,组件的标签才可以被当作插槽的模版来使用,也就是\color{red}{把v-slot写在组件上}。存在多个插槽的情况,不能简写
      2.默认插槽的语法不能和具名插槽混用,会导致作用域不明确
      3.废弃的slot-scope attribute可以添加到任意元素上,包括普通元素

    十三、动态&异步组件

    1、动态组件

    • 在动态组件上使用keep-alive元素包裹:可以在组件切换的时候,保持这些组件的状态,以避免反复重新渲染导致的性能问题
    • keep-alive要求被切换到的组件都有自己的name

    2、异步组件

    • 以工厂函数的方式定义一个组件,这个函数会异步解析组件,只有这个组件需要被渲染的时候才会触发该函数,且缓存结果供未来重渲染。
    • 使用:
    1. 局部注册
    new Vue({
      // ...
      components: {
        'my-component': () => import('./my-async-component')
      }
    })
    2.全局注册
    Vue.component(
      'async-webpack-example',
      // 这个动态导入会返回一个 `Promise` 对象。
      () => import('./my-async-component')
    )
    3. 处理加载状态
    const AsyncComponent = () => ({
      // 需要加载的组件 (应该是一个 `Promise` 对象)
      component: import('./MyComponent.vue'),
      // 异步组件加载时使用的组件
      loading: LoadingComponent,
      // 加载失败时使用的组件
      error: ErrorComponent,
      // 展示加载时组件的延时时间。默认值是 200 (毫秒)
      delay: 200,
      // 如果提供了超时时间且组件加载也超时了,
      // 则使用加载失败时使用的组件。默认值是:`Infinity`
      timeout: 3000
    })
    
    Vue.component(
      'async-webpack-example',  AsyncComponent
    )
    

    十四、处理边界情况

    1、访问根实例

    this.$root
    

    2、访问父组件实例

    this.$parent
    

    3、访问子组件实例

    ref="inputRef"
    this.$refs.inputRef
    

    4、依赖注入

    • 使用场景
      访问祖先组件的数据
    • 使用:
    1. 祖先组件:
    provide: function () {
      return {
        getMap: this.getMap
      }
    }
    2.后代组件设置inject选项接收数据:
    inject: ['getMap']
    

    十五、混入

    • 混入对象可以使用任意组件选项。组件使用混入对象时,所有混合对象的选项会被混合进该组件本身的选项。
    • 使用
    1. 基础使用
    // 定义混入对象
    var myMixin = {
      created: function() {},
    }
    // 使用混入对象的组件
    var Component = Vue.extend({
      mixins: [myMixin]
    })
    2. 全局混入
    Vue.mixin(myMixin)
    
    • 注意

    1.组件和混入对象含有同名选项:

    • 选项是对象:合并为一个对像,键名冲突,取自身健值对
    • 选项是方法:合并为数组,先调用混入对象的钩子
    • 数据:合并,冲突时以自身数据优先

    十六、自定义指令

    • 使用:
    1. 全局注册
    Vue.directive('focus', {
    //提供如下钩子函数
    // bind
    // inserted
    //update
    //componentUpdated
    //unbind
    })
    <input v-focus> //使用
    2. 局部注册
    directives: {
      focus: {
       //提供的钩子函数同上
      }
    }
    3. 给指令传参/值
    .   例如 v-my-directive:foo 中,参数为 "foo"。
            通过binding中的arg参数获取 =》 binding.arg
    .   例如:v-my-directive="1 + 1" 中,绑定值为 2,也可以通过对象字面量传多个值
            通过binding.value获取
    
    • 上述钩子函数的参数
    el:指令绑定的元素
    binding:一个对象,只读
    vnode:只读
    oldVnode:只读
    

    十七、渲染函数&JSX

    vue模板也会被编译成渲染函数
    1、渲染函数

    • 使用
      Vue.component('name',{
          render: function(createElenment[, context]) {
                 return createElement('h1',{attrs},[vnodes])    //返回一个VNode
          }
       })
    1.createElement参数
       args1: 标签名、组件选项对象、或者resolve前两个任意一个的async函数
       args2: 包含模板中attribute的数据对象(class、style、attrs、props、domProps、 
                 on、nativeOn、directives、slot、ref、key、scopedSlots、refInFor)
       args3: 由‘createElement()’构建的子级虚拟节点、文本节点。VNode唯一
    2.创建的组件如果是函数式组件(无状态、没有生命周期、无实例(this上下文)),提供context作为上下文
    3.context是一个对象,包含(props、children、slots()、data等)
    

    2、JSX

    new Vue({
      el: '#demo',
      render: function (h) {
        return (
          <AnchoredHeading level={1}>
            <span>Hello</span> world!
          </AnchoredHeading>
        )
      }
    })
    // h 作为 createElement的别名
    

    3、slots() VS children

    • slots().xxx 获取具名插槽内容
    • children获取组件内所有内容

    十八、过滤器

    1、用途

    • 文本格式化

    2、定义

    1、全局定义
    Vue.filter('myFilter',function(){})
    2、局部定义
    filter选项
    filter: {
       myFilter: function(){}
    }
    

    3、使用

    1、插值
    {{ msg | myFilter('arg1',arg2) | myFilterA}}
    // myFilter接收三个参数 msg、‘arg1’(普通字符串)、arg2
    // myFilterA 接收 myFilter的返回值作为参数
    2、v-bind表达式
    v-bind:id="id | myFilter"
    

    相关文章

      网友评论

          本文标题:Vue.js(Vue2)学习笔记

          本文链接:https://www.haomeiwen.com/subject/teaiuctx.html