vue2项目实战笔记

目录

一、vue的使用

vue的基本使用格式 

v-model

组件配置项inheritAttrs、组件实例属性$attrs和$listeners

VUE事件:


一、vue的使用

vue不兼容低版本IE

vue的基本使用格式 

 new Vue({
    el:'#app',
    inheritAttrs : false,//禁用props的Attribute 继承。下文有详细介绍
    props:{
       row: {
         type: Object,
         required: true,
        // 默认为空对象
         default:()=>({})
        
       },
       type: {
         type: String, 
         required: true,
        // 这里不能访问data中的数据,会报错。因为初始化props在前
         default: 'success',
         validator: function (value) {
          // 这个值必须匹配下列字符串中的一个
           return ['success', 'warning', 'danger'].indexOf(value) !== -1
         }
       }
    },
    data () {
       //可以定义一些常量
       let a = 123
       return {
        //只有当实例被创建时就已经存在于 data 中的属性才是响应式的。
        firstName: 'Do',
        lastName:'sfx'
       }

    },
    computed:{
        未有变量(){//默认的get
            return 值
        },
        fullName:{
            get(){
                return this.firstName + " " + this.lastName
            },
            set(val){//对fullName设置值时被调用
               
            }
        }  
    },
    watch:{
        已有变量(){},//浅度监听
        变量:{
            handler(){},
            deep:true//深度监听,深度监听一个对象开销比较大
            immediate: true //立即执行
        },
        监听一个对象,比如obj对象,只有改变obj的引用才会触发handler,改变里面的值并不会触发,解决方法是使用deep:true,
        但是开销比较大。所以可使用 'obj.a'的方式
        'obj.a':{
            handler(){},
        }
    },
    beforeCreate:function(){
        //创建前
        //实例初始化完成
    },
    created: function(){
       // 创建完成后
       //  完成数据观测 props data watch methods的运算 
    },
    beforeMount:function(){
        //dom挂载前
        // render 被执行,未挂载到界面
    },
    mounted:function(){
        //dom挂载前
        // 到这一步才可以访问到DOM
        //vue实例暴露了一些有用的实例属性与方法
        this.$data
    },
    beforeUpdate:function(){
        //更新前
    },
    updated:function(){
        //更新后
    },
    beforeDestroy:function(){
        //销毁前
    },
    destroyed:function() {
        //销毁后
    },
    activated: function(){
        // keep-alive 组件激活时调用如果你使用keep-alive进行缓存, 又希望每次切换组件的时候更新数据,那么更新数据的请求方式必须写在该钩子函数里
    },
    deactivated:function(){
        // keep-alive 组件停用时调用
    },	
    methods:{
        formDate(){
            //methods函数里面的this直接指向Vue实例
        }
    },
        //调用函数时可传入$event 获得原生event对象
        事件修饰符 
    },
    filters:{
        formDate(){...},
        example(){...}
    },
    
})
  • class与style都可以用对象或数组绑定

      当在一个自定义组件上使用 class和style 属性时,这些 class和style 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖。

  • 在 <template> 元素上使用 v-if 条件渲染分组,把 <template> 元素当做不可见的包裹元素,最终的渲染结果将不包含 <template> 元素。   注意,v-show 不支持 <template> 元素,也不支持 v-else

    <template v-if="ok">
      <h1>Title</h1>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </template>
  • 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,如果没有key值,它默认用“就地复用”策略。

    即如果数据发生了变化或者顺序被改变,Vue不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处每个元素,只是去更新相应元素的内容节点。

        如果设置了key值,每一个节点都会有唯一的身份识别。当数据发生了变化,vue可以前后对比,算出哪些节点是要重复使用或者调整顺序。

  • v-for与v-if同时使用,v-for有更高的优先级

v-model


<input v-model="searchText"> 等价于

<input :value="searchText" @input="searchText = $event.target.value" >

在子组件上使用v-model=“form” 等价于
<custom-input  :value="searchText"  @input="searchText = $event"></custom-input>

为了让它正常工作,这个组件内的 <input> 必须:
将其 value attribute 绑定到一个名叫 value 的 prop 上
在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出

改变v-model模式
 model: {
    prop: 'checked',
    event: 'change'
 },

 插槽

作用域问题: 父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的

  • 默认插槽  一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
  • 具名插槽
  • 作用域插槽
<ul>
  <li v-for="( item, index ) in items">
    //默认插槽  
    <slot></slot>

    //具名插槽
    <slot name="toolbar"></slot>

    //作用域插槽
    <slot name="listItem" :item="item" :index="index"></slot>

    //动态插槽名
    <template v-slot:[dynamicSlotName]>
        ...
    </template>
    
    

  </li>
</ul>


<todo-list>
    <template v-slot:listItem="slotProps">
        <span class="green">{{ slotProps.item }}</span>
    </template>

    //具名插槽的缩写 
    //即把 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header:
    <template #listItem="slotProps">
        <span class="green">{{ slotProps.item }}</span>
    </template>
</todo-list>

动态组件

 

组件配置项inheritAttrs、组件实例属性$attrs$listeners

2.4.0新增

组件配置项 inheritAttrs : false  禁用 Attribute 继承

以前假如使用子组件时传了a,b,c三个prop,而子组件的props选项只声明了a和b,那么渲染后c将作为html自定义属性显示在子组件的根元素上。

如果不希望这样,可以设置子组件的配置项 inheritAttrs:false,根元素就会干净多了。并不会影响 style 和 class 的绑定。

$attrs就是保存了子组件没有接受父组件的那些属性

v-bind = "obj" // 传入一个对象的所有属性
v-bind = "$attrs"

$listeners保存了父组件定义的事件

v-on = "$listeners"

VUE事件:

           v-on: click   简写 @click

           在普通元素上,v-on(@click)监听原生的DOM事件


事件处理的逻辑少,可以直接写在里面  可用$event访问原生事件对象
<input type="text" :value="msg" @input="msg = $event.target.value">

事件处理的逻辑多时可以接受一个方法
<input type="text" :value="msg" @input="handleInput">
一个参数都没传时,该方法的第一个参数是原生event对象;
handleInput(event)

传参时,可以传$event,即原生event对象  
<input type="text" :value="msg" @input="handleInput(a,b,$event)"> 
handleInput(a,b,e)

以上规则不适用与自定义事件
-------------------------------------------------

正常使用:
子组件 this.$emit('fromChild',123,456)
<使用子组件 v-for="(item, index) in 3" 
           @fromChild="onChild" /> 
onChild(a,b){} //都可以接收到  //a-> 123  b-> 456

------------------------------------------------

在父组件中通过$event接收子组件$emit传过来的值:
子组件 this.$emit('fromChild',123)

<使用子组件 v-for="(item, index) in 3" 
           @fromChild="onChild($event, index)" />   $event表示子组件传过来的第一个值:123,又自己传了下标进去
onChild(a,b){}   //a: 123  b:对应的index的值

-----------------------------------------------

子组件 this.$emit('fromChild',123,456)

<使用子组件 v-for="(item, index) in 3" 
           @fromChild="onChild($event, index)" />   $event表示传过来的第一个值:123,接收不到456,被index覆盖了
onChild(a,b){}  //a: 123  b: 对应的index的值
------------------------------------------------

想要在一个组件的根元素上直接监听一个原生事件。这时,你可以使用 v-on 的 .native 修饰符
<base-input @focus.native="onFocus"></base-input>

 事件修饰符   .stop与  .self的区别    .passive

<div class="outer" @click="log('outer')">
      outer
      <div class="mider"  @click.stop="log('mider')">
        mider
        <div class="inner"  @click="log('inner')">
          inner
        </div>
      </div>
</div>

.stop停止冒泡 :当点击inner的时候,只会打印inner和mider,因为到mider这里就停止向上冒泡了
将.stop改成 .self之后
.self表示点击的元素(event.target)是自身时触发:当点击inner的时候,会打印inner和outer, 因为并没有停止冒泡,所以outer会打印,因为event.target并不等于mider自身,所以不会打印。

.passive 不阻止默认事件,即执行默认方法
.prevent 阻止默认事件
.capture  使用事件捕获,即先执行外部元素的方法,再执行内部的

passive这个修饰符会执行默认方法。你们可能会问,明明默认执行为什么会设置这样一个修饰符呢?

        解析:【浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。】

        通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。

        这里一般用在滚动监听,@scoll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度。

原文链接:Vue事件修饰符(二).prevent .passive - 简书

<!-- Ctrl + Enter同时按下触发-->
<input type="text"  @keyup.ctrl.enter="log('text')">

<!-- Ctrl + 鼠标点击触发-->
<div class="outer" @click.ctrl="log('outer')">outer</div>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

杂乱知识点:

  1. 在 JavaScript 中对象和数组是通过引用传入子组件的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
  2. 在beforeDestory中清除定时器。更简易写法如下:
    mounted(){
        let timer = setInterval(fun,1000)
        this.$once('hook:beforedestory',()=>{
            clearInterval(timer)
        })
    }

  3. xxxxxxxxxx

工作总结:

  1. mounted中不能拿到DOM节点 , 要拿到使用v-show
  2. this.$el   当前页面的DOM
  3. this.$el.contains(e.target)
  4. this.noteList[index].disabled = false //页面不会响应  需要this.noteList.splice(index,1,{...item,disabled: false})
  5. 不缓存页面的一些体现:
    不缓存页面的一些体现
    
        1.第一次进这个页面会走mounted,如果重复进这个页面(比如动态路由,只是参数不一样),不会继续走mounted  
     
        2.切换到了其他页面,再进这个页面,又重新走mounted
    

6.组件内的beforeRouteEnter()

组件内的beforeRouteEnter(to, from, next)
1. 好像主页面路由里面才有效
2.跟一个页面有没有缓存没有关系,只要是从其他页面进来就会触发。如果还是这个页面,只是参数不一样,不会触发(比如动态路由) 

3.这个钩子函数不能获取到this实例,但可以通过next(),传入回调函数,next(vm=>{
       //vm访问组件实例
})

来源:https://segmentfault.com/a/1190000039921701

beforeRouteUpdate(to, from, next) {
  // 在当前路由改变,但是该组件被复用时调用
  // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
  // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
  // 可以访问组件实例 `this`
  console.log('beforeRouteUpdate 组件内更新守卫');
  next();
},
beforeRouteLeave(to, from, next) {
  // 导航离开该组件的对应路由时调用
  // 可以访问组件实例 `this`
  console.log('beforeRouteLeave 组件内离开守卫');
  next();
}

7.使用vuex存储用户信息时,刷新页面会数据丢失,建议搭配localStorage。

8.如果path定义的不是动态路由,页面跳转时,使用params传参可以,但是刷新后就没有了。

(因为用params一般是 path定义的是动态路由时,用这个传参来拼接路由的)

所以建议使用query传参

9.动态路由的跳转方式:

{
    component: ...,
    path: '/board/:id',
    name: 'board'
}

//跳转方式1:
this.$router.push({
    path: '/board/12'
})

//跳转方式2: 建议
this.$router.push({
    name: 'board',
    params: { id : 12}
})

10.若线上需要对path进行加密,那么都使用name去跳转。  path加密且存在动态路由的情况,跳转方式用上面提到的动态路由跳转方式2。

11.在路由导航守卫中,router.addRoutes之后的next()可能会失效,因为可能next()的时候路由并没有完全add完成

我们可以通过next(to)巧妙的避开这个问题。这行代码会重新进入router.beforeEach这个钩子,这时候再通过next()来释放钩子,就能确保所有的路由都已经挂在完成了。

12.tab页签切换时,调对应页签组件的接口,不要一次性全部请求。解决方法:

<el-tabs v-model='activeTab'>
    <el-tab-pane name='tab-1'>
        <组件 v-if='activeTab== 'tab-1'><组件>
    </el-tab-pane>
     <el-tab-pane name='tab-2'>
        <组件 v-if='activeTab== 'tab-2'><组件>
    </el-tab-pane>
</el-tabs>

但有一个问题,每次点击这个tab组件都会重新挂载一次,就是tab来回切换的时候会重复请求,这时候我们就可以用到

<keep-alive>

keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。 它是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中

<el-tabs v-model='activeTab'>
    <el-tab-pane name='tab-1'>
        <keep-alive>
            <组件 v-if='activeTab== 'tab-1'><组件>
        </keep-alive>
    </el-tab-pane>
     <el-tab-pane name='tab-2'>
        <keep-alive>
            <组件 v-if='activeTab== 'tab-2'><组件>
        </keep-alive>
    </el-tab-pane>
</el-tabs>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值