美文网首页
vue使用技巧

vue使用技巧

作者: 拾钱运 | 来源:发表于2020-07-22 16:36 被阅读0次

1.require.context()

父组件中导入多个组件

import titleCom from '@/components/home/titleCom'
import bannerCom from '@/components/home/bannerCom'
import cellCom from '@/components/home/cellCom'
components:{titleCom,bannerCom,cellCom}

使用require.context()

const path=require('path')
const files=require.context('@/commponent/home',false,'/\.vue$/')
const moudules={}
files.keys().from(key=>{
    const name=path.basename(key,'.vue')
    modules[name]=files(key).default || files(key)
})
components:modules
api描述:
  /**
@params directory  需要检索的目录
@params useSubdirectories  是否检索子目录
@params   regExp   匹配正则表达式,一般为文件名
*/
require.context(directory,useSubdirectories,regExp)

2.watch

2.1 常用做法

1.场景:表格初始进来的时候需要调查询接口,当input值改变的时候也需要在调用查询

created(){
  this.getList()
},
watch: {
  inpVal(){
    this.getList()
  }
}

可以这样写

watch:{
  inpVal:{
    handler:'getList',
    immediate:true
  }
}

2.watch的深度监听

watch:{
  inpValObj:{
    handler(newVal,oldVal){
      console.log(newVal)
      console.log(oldVal)
    }
  },
deep:true
}

注意:因为索引同一个对象/数组,vue不会保留修改之前值的副本
所以深度监听随然可以监听到对象的改变,但是无法监听到具体对象中哪个属性的变化

3. 14种组件通讯

1.props
  • props :[] 不建议
  • props:{}
// 对象
props:{
 inpVal:{
  type:String, //传入值限定类型
  // type 值可为String,Number,Boolean,Array,Object,Date,Function,Symbol
  // type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认
  required: true, //是否必传
  default:200,  //默认值,对象或数组默认值必须从一个工厂函数获取如 default:()=>[]
  validator:(value) {
    // 这个值必须匹配下列字符串中的一个
    return ['success', 'warning', 'danger'].indexOf(value) !== -1
  }
 }
}
2.$emit
//父组件
<home @title="title">
//子组件
this.$emit('title',[{title:'这是title,传递给父组件的值'}])
3.vuex
state:定义存储数据的仓库,可通过this.$store.state或mapState访问
getter:获取store值,可认为是store的计算属性,可通过this.$store.getter或者mapGetters访问
mutation:同步改变store值,为什么会设计成同步,因为mutation是直接改变store值,vue对操作进行了记录,如果是异步无法追踪改变,可通过mapMutaions调用
action:异步调用函数执行mutaion,进而改变store值,可通过this.$dispatch或mapActions访问
modules:模块,如果状态过多,可以拆分成模块,最后入口通过...结构引入

例子:

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

mutation和action的区别

  • mutation 同步修改state值
  • action 异步修改state值
  • mutation扮演的角色:专注于修改state,理论上是修改state的唯一途径。
  • action 业务代码、异步请求

理解为:如果业务种异步操作,就用action,操作state唯一的途径是mutation。

4.listeners

2.4.0新增
1.场景:如果父传子有很多值那么在子组件需要定义多个解决attrs获取子传父中未在props定义的值

// 父组件
<home title="这是标题" width="80" height="80" imgUrl="imgUrl"/>

// 子组件
mounted() {
  console.log(this.$attrs) //{title: "这是标题", width: "80", height: "80", imgUrl: "imgUrl"}
},

相对应,如果子组件定义了props,打印的值就会剔除定义的属性

props:{
  width:{
    type:String,
    default:''
  }
},
mounted(){
  console.log(this.$attrs)//{title: "这是标题", height: "80", imgUrl: "imgUrl"}没有width
}

2.场景子组件需要父组件的方法可以通过listeners,传入内部组件——在创建更高层次的组件时非常有用

// 父组件
<home @change="change"/>

// 子组件
mounted() {
  console.log(this.$listeners) //即可拿到 change 事件
}

如果孙组件要访问父组件的属性和方法,直接一级一级传下去就好
3.inheritAttrs

//父组件
<home title="这是标题" width="80" height="80" imgUrl="imgUrl">
//子组件
mounted(){
  console.log(this.$attrs)/{title: "这是标题", width: "80", height: "80", imgUrl: "imgUrl"}
}
inheritAttrs默认值为true,true的意思是将父组件中除了props外的属性添加到子组件的根节点上(说明,即使设置为true,子组件仍然可以通过$attr获取到props意外的属性)
将inheritAttrs:false后,属性就不会显示在根节点上

5.provide和inject

2.2.0新增
描述:provide和inject主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
这对选项需要一起使用
允许一个祖先组件向其所有子孙后代注入一个不依赖,不论组件层次多深,并在起上下游关系成立的时间里始终生效。

//父组件:
provide:{//provide是一个对象,提供一个属性和方法
  foo:'这是foo',
  fooMethod:()=>{
    console.log('父组件fooMethod被调用')
  }
}
//子组件
inject:['foo','fooMethod'],//数组或对象,注入到子组件
mounted(){
  this.fooMethod()
  console.log(this.foo)
}
//在父组件下面所有的子组件都可以利用inject

provide和inject绑定并不是响应的。
如果传入一个可监听的对象,那么其对象的属性还是响应式的,对象是因为是引用类型

//父组件
provide:{
  foo:'这是foo'
},
mounted(){
  this.foo='这是新的foo'
}
//子组件
inject:['foo'],
mounted(){
  console.log(this.foo)//这是foo
}

6.children

父实例children:子实例

//父组件
mounted(){
  console.log(this.$children)
  //可以拿到一级子组件的属性和方法
//所以就可以直接改变data,或者调用methods方法
}
//子组件
mounted(){
  console.log(this.$parent)//可以拿到parent的属性和方法
}

顺序不保证,也不是响应式的。
只能拿到一级父组件和子组件

7.$refs

<home ref="home"/>
mounted(){
  console.log(this.$refs.home)//即可拿到子组件的实例,就可以直接操作data和methods
}

8.$root

// 父组件
mounted(){
  console.log(this.$root) //获取根实例,最后所有组件都是挂载到根实例上
  console.log(this.$root.$children[0]) //获取根实例的一级子组件
  console.log(this.$root.$children[0].$children[0]) //获取根实例的二级子组件
}

9. .sync

在vue@1.x的时候曾作为双向绑定功能存在,即子组件可以修改父组件中的值;

在vue@2.0 由于违背单项数据流的设计被干掉了
在vue@2.3.0+以上版本又重新引入了这个.sync修饰符

//父组件
<home :title.sync="title"/>
//编译时会被拓展为
<home :title="title" @update:title="val=>title=val">

//子组件
//所有子组件可以通过$emit触发update方法改变
mounted(){
  this.$emit('update:title','这是新的title')
}

例子

//父组件
<template>
    <info :value="myValue" @valueChanged="e => myValue = e"></info>
</template>
<script>
    inport info from './info.vue';
    export default {
        components: {
            info,
        },
        data() {
            return {
                myValue: 1234,
            }
        },
    }
</script>

//子组件

// info.vue组件定义了一个value 属性, 和一个valueChanged事件
<template>
    <div>
        <input @input="onInput" :value="value"/>
    </div>
</template>

<script>
export default {
    props: {
        value: {
            type: String
        }
    },
    methods: {
        onInput(e) {
            this.$emit("valueChanged", e.target.value)
        }
    }
}
</script>

可以这样写

// index.vue组件 父
<info :value.sync="myValue"></info>
....
// info.vue组件 子
...
methods: {
    onInput(e) {
        this.$emit("update:value", e.target.value)
    }
}
用法2

如果一个组件有多个prop都要实现双向绑定,根据上面学到的知识,只需要每个prop加sync修饰符

<info :a.sync="value1" :b.sync="value2" :c.sync="value2" :d.sync="value2"></info>

<info v-bind.sync="obj"></info>
<script>
..
data() {
    obj: {a: '', b: '', c: '', d: ''}
}
..
</script>

10.EventBus

1.就是声明一个全局vue实例变量EventBus,把所有的通信数据,事件通监听到存储到这个变量上;
2.类似于Vuex。但这种方式只使用与极小的项目
3.原理就是利用和emit并实例化一个全局vue实现数据共享

//在main.js
Vue.prototype.$eventBus=new Vue()
//传值组件
this.$evnentBus.$emit('eventTarget','这是eventTatget传过来的值')
//接收组件
this.$eventBus.$on('eventTarget',v=>{
  console.log('eventTarget',v)//这是eventTarget传来的值
})

4.可以实现平级,嵌套组件传值,但是对应的事件名eventTarget必须全局唯一的

11.路由传参

1.方案一 :会暴露在url中

//路由定义
{
  path:' /describe/:id',
  name:'Describe',
  component:Describe
}
//页面传参
this.$router.push({
  path:`/describe/${id}`,
})
//页面获取
this.$route.params.id

2.方案二 不会暴露到url中,但刷新的时候会丢失数据

//路由定义
{
  path:'/describe',
  name:'Describe',
  component:Describe
}
//页面传参
this.$router.push({
  name:'Describe',
  params:{
    id:id
  }
})
//页面获取
this.$route.params.id

3.方案三:会拼接在url中

//路由定义
{
  path:'/describe',
  name:'Describe',
  component:Describe
}
//页面传参
this.$router.push({
  path:'/describe',
  query:{
      id:id
  }
})
//页面获取
this.$router.query.id

12.Vue.observalbe

2.6.0新增
用法:让一个对象可响应。Vue内部就会用它来处理data函数返回的对象

返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新;也可以作为最小化的跨组件状态存储器,用于简单的场景

通讯原理实质上是利用Vue.observable实现一个简易的vuex

sotre.js
import  Vue from 'vue'
export const store=Vue.observable({count:0})
export  const mutations={
  setCount(count){
    store.count=count
  }
}
// vue中使用
<template>
  <div>
      <label for ="bookNum">数量</label>
      <button @click="setCount(count+1)">+</button>
      <span>{{count}}</span>
      <button @click="setCount(count-1)">-</button>
  </div>
<template>
<script>
  import {store ,mutations} from '../sotre/sotre' vue2.6新增的observable
  export default {
      name:'Add',
      computed:{
        count(){
          return store.count
        }
      },
      methods:{
        setCount:mutations.setCount
      }
   },

</script>

13.render函数

1.场景:有些代码在template里面写会重复很多,所以这个时间render函数就有作用了

/ 根据 props 生成标签
// 初级
<template>
  <div>
    <div v-if="level === 1"> <slot></slot> </div>
    <p v-else-if="level === 2"> <slot></slot> </p>
    <h1 v-else-if="level === 3"> <slot></slot> </h1>
    <h2 v-else-if="level === 4"> <slot></slot> </h2>
    <strong v-else-if="level === 5"> <slot></slot> </stong>
    <textarea v-else-if="level === 6"> <slot></slot> </textarea>
  </div>
</template>
// 优化版,利用 render 函数减小了代码重复率
<template>
  <div>
    <child :level="level">Hello world!</child>
  </div>
</template>
<script>
   import Vue from 'vue'
  Vue.component('child',{
      render(createElement){
        const tag=['div','p','strong','h1','h2','textarea'][this.level-1]
        return createElement(tag,this.$slots.default)
      },
    props:{
       level:{type:Number,required:true}
      }
    })
export defatult{
    name:'zmq',
    data(){return {level;3}}
}
</script>

2.render和template对比
render适合复杂逻辑,template适合简单逻辑
render属于自定render函数,template 属于声明是渲染
render性能告,template性能低

注意

注意vue组件中的定时器要在组件销毁的时候,清除掉
vue组件销毁的时候,会解绑所有指令以及事件监听

相关文章

  • VScode 使用技巧笔记

    一、vue开发技巧: 使用技巧 常用快捷键总结 v开头 vue文件:页面结构vbase、vbase-ts、vbas...

  • vue使用技巧

    1.牵扯到ajax获取数据在html里面里渲染的时候,必须在要渲染的html里使用v-if="你的数据名",也就是...

  • vue使用技巧

    1.require.context() 父组件中导入多个组件 使用require.context() api描述:...

  • webstorm和vscode使用技巧(持续更新)

    webstorm使用技巧1、修改模板(如vue组件模板)file--settting--搜template--fl...

  • vue使用小技巧

    如何解决子组件属性设置在根元素上 应用场景:当我们去调用组件时,会有一个需求是将一些属性传入子组件。当我们定义了p...

  • vue使用小技巧

    1. lazy 2. number 3. trim 4. js中的delete & Vue.delete 5. 事...

  • 10个Vue开发技巧

    参考文章:10个Vue开发技巧 一、路由参数解耦 知道这个写法,但是没有使用过,可参考笔记vue-router五。...

  • webstorm单标签设置成双标签展开解决iview中col展开

    大家好!我是木瓜太香,今天给大家带来一个 webstorm 小技巧 场景:有使用过 vue 框架并且使用 ivie...

  • vue的几个使用技巧

    1. 合理使用watch的immediate属性 通常我们在使用watch的时候是这么写的,例如有请求需要再也没初...

  • vue优雅使用技巧(一)

    vue优雅使用 1. 高频组件全局引入 使用Vue.use()方法弊端: 需要多次import 引入组件 使用re...

网友评论

      本文标题:vue使用技巧

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