关于Vue.js组件巨详细的一篇文章

2023-11-15

Vue.js 组件

组件用于封装页面的部分功能,将功能的结构、样式、逻辑代码封装为整体

提高功能的复用性与可维护性,更好地专注于业务逻辑

组件使用时为自定义 HTML 标签形式,通过组件名作为自定义标签名

<div id="app">
    <!-- 普通 HTML 标签 -->
    <p>P标签内容</p>
    <!-- Vue.js 组件 -->
    <my-com></my-com>
</div>

全局注册

全局注册的组件在注册后可以用于任意实例或组件中

Vue.component('组件名', { /* 选项对象 */ })

注意:全局注册必须设置在根 Vue 实例创建之前

组件基础

本质上,组件是可复用的 Vue 实例,所以它们可以与 new Vue 接收相同的选项,例如 data、methods 以及生命周期钩子等

仅有的例外是像 el 这样的根实例特有的选项

组件命名规则

  • kebab-case: “my-component”
  • PascalCase: “MyComponent”
Vue.component('my-component', {/* 选项对象 */})
Vue.component('MyComponent', {/* 选项对象 */})

注意:无论采用那种命名方式,在 DOM 中都只有 Kebab-case 可以使用

<div id="app">
  <my-com-a></my-com-a>
  <!-- <MyComA></MyComA> -->
  <my-com-b></my-com-b>
  <!-- <MyComB></MyComB> -->
</div>
<!-- ============================== -->
<script>
  // kebab-case 进行注册
  Vue.component('my-com-a', {
    template: '<div>这是a组件的内容</div>'
  });
  // PascalCase 进行注册
  Vue.component('MyComB', {
    template: '<div>这是b组件的内容</div>'
  });
  new Vue({
    el: '#app',
    data: {
    }
  })
</script>

template 选项

template 选项用于设置组件的结构,最终被引入根实例或其他组件中

Vue.component('my-com-a', {
  template: `
    <div>
        <h3>组件A的标题内容</h3>
    </div>
  `
});

注意:组件必须只有一个根元素

data 选项

data 选项用于存储组件的数据,与根实例不同,组件的 data 选项必须为函数,数据设置在返回值对象中

Vue.component('my-com-a', {
  template: `
    <div>
        <h3>组件A的标题内容:{{ title }}</h3>
    </div>
  `,
  data: function () {
      return {
          title: "示例内容"
      }
  }
});

这种实现方式是为了确保每个组件实例可以维护一份被返回对象的独立的拷贝,不会互相影响

局部注册

局部注册的组件只能用在当前实例或组件中

new Vue({
    components: {
        'my-component-a': {
            template: `<h3> {{ title }} </h3>`,
            data () {
                return {title: "a 组件示例内容"}
            }
        },
        'my-component-b': {
            template: `<h3> {{ title }} </h3>`,
            data () {
                return {title: "b 组件示例内容"}
            }
        }
    }
}) 

单独配置组件的选项对象

var MyComponentA = { /* ... */ };
var MyComponentB = { /* ... */ };

new Vue({
    el: "#app",
    components: {
        "my-component-a" : MyComponentA,
        "my-component-b" : MyComponentB
    }
})

ES6 的对象属性简写

new Vue({
    el: "#app",
    components: {
        MyComponentA,
        MyComponentB
    }
})

组件通信

问题:
子组件如何获取父组件中的数据?
父组件如何得知子组件的数据变更?
如果是更加复杂的组件关系呢?

在组件间传递数据的操作,称为组件通信

  • 父传子
  • 子传父
  • 非父子传
  • 其他通信方式

父组件向子组件传值

通过子组件的 props 选项接收父组件的传值

Vue.component('my-component', {
  props: ['title'],
  template: '<h3> {{ title }} </h3>'
})

注意:props 不要与 data 存在同名属性

父组件设置方式如下:

<div id="app">
  <my-component-a title="示例内容1"></my-component-a>
  <my-component-a :title="'示例内容2'"></my-component-a>
  <my-component-a :title="item.title"></my-component-a>
</div>
<!-- ======================= -->
<script>
  new Vue({
    el: "#app",
    data: {
      item: {
        title: "父组件的数据"
      }
    }
  })
</script>

props 命名规则

建议 prop 命名使用 camelCase,父组件绑定时使用 kebab-case

Vue.component('my-component', {
  props: ['myTitle'],
  template: "<h3> {{ myTitle }} </h3>"
})
<div id="app">
  <my-component-a title="示例内容1"></my-component-a>
  <my-component-a :title="'示例内容2'"></my-component-a>
  <my-component-a :title="item.title"></my-component-a>
</div>

单项数据流

父子组件间的所有 prop 都是单向下行绑定的

如果子组件要处理 prop 数据,应当存储在 data 中后操作

Vue.component({
  props: ['initialTitle'],
  template: '<h3> {{myTitle}} </h3>',
  data () {
    return {
      myTitle: this.initialTitle
    }
  }
})

注意:如果 prop 为数组或对象时,子组件操作将会影响到父组件的状态

props 类型

prop 可以设置类型检查,这时需要将 props 更改为一个带有验证需求的对象,并指定对应类型

Vue.component({
  props: {
    parStr: String,
    parArr: Array,
    parAny: null // parAny: undefined
  },
  template: `
    <div>
      {{ parStr }}
      {{ parArr }}
      {{ parAny }}
    </div>
  `
})
<script>
  new Vue({
    el: "#app",
    data: {
      str: '示例内容',
      arr: [1, 2, 3],
      any: "任意类型均可"
    }
  })
</script>
<!-- ======================= -->
<div id="app">
  <my-component-a
    :par-str = "str"
    :par-arr = "arr"
    :par-any = "any"
  ></my-component-a>
</div>

prop 还可以同时指定多个类型,通过数组方式保存即可

Vue.component('MyComponentA', {
  props: {
    parData: [String, Number]
  },
  template: `
    <div>
      {{ parData }}
    </div>
  `
})

props 验证

当 prop 需要设置多重规则时,可以将 prop 的值设置为选项对象

之前的类型检测功能通过 type 选项设置

Vue.component('MyComponentA', {
  props: {
    parNum: {
      type: Number
    },
    parData: {
      type: [String, Boolean]
    }
  },
  template: `
    <div>
      {{ parNum }}
      {{ parData }}
    </div>
  `
})

required 用于设置数据为必填项

Vue.component('MyComponentA', {
  props: {
    parNum: {
      type: Number,
      required: true
    }
  },
  template: `
    <div>
      {{ parNum }}
    </div>
  `
})

default 用于给可选项指定默认值,当父组件未传递数据时生效

Vue.component('MyComponentA', {
  props: {
    parNum: {
      type: Number,
      dafault: 100
    }
  },
  template: `
    <div>
      {{ parNum }}
    </div>
  `
})

注意:当默认值为数组或对象是,必须为工厂函数返回的形式

Vue.component('MyComponentA', {
  props: {
    parArr: {
      type: Array,
      default: function () {
        return [1, 2, 3]
      }
    }
  },
  template: `
    <div>
      {{ parArr }}
    </div>
  `
})

validator 用于给传入的 prop 设置校验函数,return 值为 false 时 Vue.js 会发生警告

Vue.component('MyComponentA', {
  props; {
    type: String,
    validator: function (value) {
      return value.startsWitn('lagou');
    }
  },
  template: `
    <div>
      {{ parStr }}
    </div>
  `
})

注意:验证函数中无法使用实例的 data、methods 等功能

非 props 属性

当父组件给子组件设置了属性,但此属性在 props 中不存在,这时会自动绑定到子组件的根元素上

<script>
Vue.component('MyComponentA', {
  template: `<p>子组件内容</p>`
})
</script>

<!-- ================== -->

<div id="app">
  <my-component-a
    demo-attr="示例属性"
    title="示例title"
    style="height: 200px"
    class="colorBlue"
  ></my-component-a>
</div>

如果组件根元素已经存在了对应属性,则会替换组件内部的值

class 与 style 是例外,当内外都设置时,属性会自动合并

Vue.component('MyComponentA', {
  template: `
    <p title="原始title" class="fl" style="width: 200px;">子组件内容</p>
  `
})

如果不希望继承父组件设置的属性,可以设置 inheritAttrs: false,但是只适用于普通书写,class 与 style 不受影响

Vue.component('MyComponentA', {
  inheritAttrs: false,
  template: `
    <p title="原始title" class="fl" style="width: 200px;">子组件内容</p>
  `
})

子组件向父组件传值

子向父传值需要通过自定义事件实现

商品为子组件,购物车为父组件,父组件需统计商品个数,就需要在子组件个数变化时传值给父组件

<script>
  new Vue({
    el: "app",
    data: {
      products: [
        { id; 1, title: '苹果1斤' },
        { id; 2, title: '橙子2个' },
        { id; 3, title: '香蕉3根' }
      ],
      totalCount: 0
    }
  })
</script>
<!-- ========================== -->
<div id="app">
  <h3>购物车</h3>
  <product-item
    v-for="product in products"
    :title="product.title"
    :key="product.id"
  ></product-item>
  <p>总数为:{{ totalCount }} </p>
</div>

<!-- 子组件 -->
<script>
Vue.component("product-item", {
  props: ['title'],
  template: `
    <div>
      <span>商品名称:{{ title }};商品个数:{{ count }}</span>
      <button @click="countIns"> +1 </button>
    </div>
  `,
  data () {
    return { count: 0 }
  }.
  methods: {
    countIns () {
      this.count++
    }
  }
})
</script>

子组件数据变化时,通过 $emit() 触发自定义事件

Vue.component('product-item', {
  // ...
  methods: {
    countIns () {
      this.$emit('count-change');
      this.count++
    }
  }
})

子组件向父组件传值
父组件监听子组件自定义事件,并设置处理程序

<div id="app">
  <!-- ... -->
  <product-item
    @count-change="totalCount++"
  ></product-item>
  <!-- ... -->
</div>

自定义事件传值

子组件触发事件时可以向父组件传值

Vue.component("product-item", {
  props: ['title'],
  template: `
    <div>
      <span>商品名称:{{ title }};商品个数:{{ count }}</span>
      <button @click="countIns1"> +1 </button>
      <button @click="countIns2"> +5 </button>
    </div>
  `,
  data () {
    return { count: 0 }
  }.
  methods: {
    countIns1 () {
      this.$emit('count-change', 1);
      this.count++
    }
    countIns5 () {
      this.$emit('count-change', 5);
      this.count += 5
    }
  }
})

父组件在监听事件时需要接受子组件传递的数据

<div id="app">
  <!-- ... -->
  <product-item
    @count-change="totalCount += $event"
  ></product-item>
  <!-- ... -->
</div>

父组件在监听事件时需要接受子组件传递的数据

<div id="app">
  <!-- ... -->
  <product-item
    @count-change="onCountChange"
  ></product-item>
  <!-- ... -->
</div>
<!-- ======================================= -->
<script>
new Vue({
  methods: {
    onCountChange (productCount) {
      this.totalCount += productCount;
    }
  }
})
</script>

组件与 v-model

v-model 用于组件时,需要通过 props 与自定义事件实现

<div id="app">
  <p>输入内容为:{{ iptValue }}</p>
  <com-input v-model="iptValue"></com-input>
</div>
<script>
  new Vue({
    el: "#app",
    data: {
      iptValue: ''
    },
    components: {
      ComInput
    }
  })
</script>
<!-- ======================= -->
<script>
  var ComInput = {
    props:['value'],
    template: `
      <input
        type="text"
        :value="value"
        @input="$emit('input', $event.target.value)"
      >
    `
  }
</script>

非父子组件传值

兄弟组件或完全无关的两个组件

  • 兄弟组件传值
  • EventBus
  • 其他传值方式

兄弟组件传值

兄弟组件可以通过父组件进行数据中转

<!-- 父 -->
<script>
  new Vue({
    el: "#app",
    data: {
      value: ''
    }
  })
</script>
<div id="app">
  <com-a
    @value-change="value = $event"
  ></com-a>
  <com-b
    :value="value"
  ></com-b>
</div>

<!-- 子级A -->
<script>
  Vue.component('ComA', {
    template: `
      组件A的内容:{{ value }}
      <button 
        @click="$emit('value-change', value)"
      >发送</button>
    `,
    data () {
      return {
        value: '示例内容'
      }
    }
  })
</script>

<!-- 子级B -->
<script>
  Vue.component('ComA', {
    props: ['value'],
    template: `
      <div>
        组件B接收到:{{ value }}
      </div>
    `
  })
</script>

EventBus

当组件嵌套关系复杂时,根据组件关系传值会较为繁琐

组件为了数据中转,data 中会存在许多与当前组件功能无关的数据

  • EventBus(事件总线)是一个独立的事件中心,用于管理不同组件间的传值操作
  • EventBus 通过一个新的 Vue 实例来管理组件传值操作,组件通过给实例注册事件、调用事件来实现数据传递
// Event.js
var bus = new Vue()

发送数据的组件触发 bus 事件,接收的组件给 bus 注册对应事件

Vue.component("product-item", {
  template: `
    <div>
      <span>商品名称:苹果;商品个数:{{ count }}</span>
      <button @click="countIns"> +1 </button>
    </div>
  `,
  data () {
    return { count: 0 }
  }.
  methods: {
    countIns () {
      bus.$emit('countChange', 1);
      this.count++;
    }
  }
})

给 bus 注册对应事件通过 $on() 操作

Vue.component("product-total", {
  template: `
    <p> 总个数为:{{ totalCout }} </p>
  `,
  data () {
    return { totalCout: 0 }
  }.
  created () {
    bus.$on('countChange', (productCount) => {
      this.totalCount += productCount;
    })
  }
})

最后创建根实例执行代码即可

其他通信方式

  • $root
  • $refs

$root

$root 用于访问当前组件树根实例,设置简单的 Vue 应用时可以通过此方式进行组件传值

<div id="app">
  <p>父组件数据:{{ count }}</p>
  <com-a></com-a>
  <com-b></com-b>
</div>
<script>
  var ComA = {
    template: `
      <div>
        组件 A :{{ $root.count }}
        <button @click="clickFn"> +1 </button>
      </div>
    `,
    methods: {
      clickFn () {
        this.$root.count++;
      }
    }
  }

  var ComB = {
    template: `
      <div>
        组件 B :{{ $root.count }}
        <button @click="clickFn"> +1 </button>
      </div>
    `,
    methods: {
      clickFn () {
        this.$root.count++;
      }
    }
  }

  new Vue({
    el: "#app",
    data: {
      count: 0
    },
    components: {
      ComA,
      ComB
    }
  })
</script>

除了 $root,Vue.js 中还提供了 $parent 与 $children 用于便捷访问父子组件

$refs

$refs 用于获取设置了 ref 属性的 HTML 标签或子组件

给普通 HTML 标签设置 ref 属性,$refs 可以获取 DOM 对象

<div id='app'>
  <input type="text" ref="inp">
  <button @click="fn">按钮</button>
</div>
<!-- ================= -->
<script>
new Vue({
  el: '#app',
  methods: {
    fn () {
      this.$refs.inp.focus();
    }
  }
})
</script>

给子组件设置 ref 属性,渲染后可通过 $refs 获取子组件实例

<div id='app'>
  <com-a ref="comA">按钮</com-a>
</div>
<!-- ================= -->
<script>
new Vue({
  el: '#app',
  components: {
    ComA
  },
  mounted () {
    console.log(this.$refs);
    this.$refs.comA.value = '修改了子组件数据'
  }
})
</script>

给子组件设置 ref 属性,渲染后可通过 $refs 获取子组件实例

<div id='app'>
  <com-a ref="comA">按钮</com-a>
</div>
<!-- ================= -->
<script>

var ComA = {
  template: `<p>组件 A:{{ value }}</p>`,
  data () {
    return {
      value: '这是组件A的数据'
    }
  }
}

new Vue({
  el: '#app',
  components: {
    ComA
  },
  mounted () {
    console.log(this.$refs);
    this.$refs.comA.value = '修改了子组件数据'
  }
})
</script>

组件插槽

组件插槽可以便捷的设置组件内容

<div id='app'>
  <com-a>
    示例内容
    <span>组件的主体内容</span>
  </com-a>
</div>

单个插槽

如果我们希望组件标签可以像 HTML 标签一样设置内容,那么组件的使用灵活度会很高

<div id='app'>
  <p>示例内容1</p>
  <com-a>示例内容2</com-a>
</div>

但平常我们书写的组件,组件首尾标签中书写的内容会被抛弃

<script>
  Vue.component('com-a', {
    template: `
      <div>
        <h3>组件标题</h3>
      </div>
    `
  })
</script>
<!-- ==================== -->
<div id='app'>
  <com-a>
    示例内容
    <span>组件的主体内容</span>
  </com-a>
</div>

我们需要通过 <slot> 进行插槽设置

<script>
  Vue.component('com-a', {
    template: `
      <div>
        <h3>组件标题</h3>
        <slot></slot>
      </div>
    `
  })
</script>
<!-- ==================== -->
<div id='app'>
  <com-a>
    示例内容
    <span>组件的主体内容</span>
  </com-a>
</div>

需要注意模板内容的渲染位置

<div id='app'>
  <com-a>
    这里只能访问父组件的数据
    {{ parValue }}
  </com-a>
</div>
<!-- ==================== -->
<script>
  new Vue({
    el: "#app",
    data: {
      parValue: '父组件数据'
    },
    components: {
      ComA
    }
  })
</script>

我们可以在 <slot> 中为插槽设置默认值,也称为后备内容

<scripiiiiiiiiii>
  var ComA = {
    template: `
      <div>
        <p>组件 A:</p>
        <slot>这是默认文本</slot>
      </div>
    `,
    data () {
      return {
        value: '子组件数据'
      }
    }
  }
</scripiiiiiiiiii>
<!-- ==================== -->
<div id='app'>
  <com-a></com-a>
</div>

具名插槽

如果组件中有多个位置需要设置插槽,据需要给 <slot> 设置 name,称为具名插槽

<com-a>
    <template v-slot:header>
        <h1>组件头部内容</h1>
    </template>
    <template v-slot:default>
        <p>组件主体内容第一段</p>
        <p>组件主体内容第二段</p>
    </template>
    <template v-slot:footer>
        <h1>组件底部内容</h1>
    </template>
</com-a>

<!-- 简写 -->
<com-a>
    <template #header>
        <h1>组件头部内容</h1>
    </template>
    <template #default>
        <p>组件主体内容第一段</p>
        <p>组件主体内容第二段</p>
    </template>
    <template #footer>
        <h1>组件底部内容</h1>
    </template>
</com-a>
<!-- =================================== -->
<script>
Vue.component('ComA', {
  template: `
    <div>
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
  `
});
</script>

作用域插槽

用于让插槽可以使用子组件的数据

组件将需要被插槽使用的数据通过 v-bind 绑定给 <slot>,这种用于给插槽传递数据的属性称为插槽 prop

var ComA = {
  template: `
    <div>
      <p>组件 A:</p>
      <slot :value="value">这是默认文本</slot>
    </div>
  `,
  data () {
    return {
      value: '子组件数据'
    }
  }
}

组件绑定数据后,插槽中需要通过 v-slot 接收数据

<div id="app">
  <com-a>
    <template v-slot:default="dataObj">
      {{ dataObj.value }}
    </template>
  </com-a>
</div>

如果只存在默认插槽,同时又需要接收数据,可以进行简写

<div id="app">
  <com-a v-slot:default="dataObj">
    {{ dataObj.value }}
  </com-a>
</div>

<!-- 更加简化的写法 -->
<div id="app">
  <com-a v-slot="dataObj">
    {{ dataObj.value }}
  </com-a>
</div>

还可以通过 ES6 的解构操作进行数据接收

<div id="app">
  <com-a v-slot:default="{ value }">
    {{ value }}
  </com-a>
</div>

动态组件

动态组件适用于多个组件频繁切换的处理

<component> 用于将一个 ‘元组件’ 渲染为动态组件,以 is 属性值决定渲染那个组件

<div id='app'>
  <component :is=" 'ComA' "></component>
</div>

用于实现多个组件的快速切换,例如选项卡效果

<div id="app">
  <button
    v-for="title in titles"
    :key="title"
    @click="currentCom = title"
  > {{ title }} </button>
  <component :is="currentCom"></component>
</div>

<script>
  var ComA = { template: `<div> A组件内容 </div>` };
  var ComC = { template: `<div> B组件内容 </div>` };
  var ComB = { template: `<div> C组件内容 </div>` };

  new Vue({
    el: "#app",
    data: {
      titles: ['ComA', 'ComB', 'ComC'],
      currentCom: 'ComA'
    },
    components: {
      ComA,
      ComB,
      ComC
    }
  })
</script>

is 属性会在每次切换组件时,Vue 都会创建一个新的组件实例

  var ComA = { 
    template: `<div> A组件内容:<input type="text"> </div>` 
  };
  var ComC = { 
    template: `<div> B组件内容:<input type="text"> </div>` 
  };
  var ComB = { 
    template: `<div> C组件内容:<input type="text"> </div>` 
  };

keep-alive 组件

主要用于保留组件状态或避免组件重新渲染

<keep-alive>
  <component :is="currentCom"></component>
</keep-alive>

include 属性用于指定那些组件会被缓存,具有多种设置方式

<keep-alive include="ComA,ComB,ComC">
  <component :is="currentCom"></component>
</keep-alive>
<keep-alive include="['ComA', 'ComB', 'ComC']">
  <component :is="currentCom"></component>
</keep-alive>
<keep-alive include="/Com[ABC]/">
  <component :is="currentCom"></component>
</keep-alive>

exclude 属性用于指定哪些组件不会被缓存

<keep-alive exclude="ComD">
  <component :is="currentCom"></component>
</keep-alive>

max 属性用于设置最大缓存个数

<keep-alive max="5">
  <component :is="currentCom"></component>
</keep-alive>

过渡组件

用于在 Vue 插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡、动画效果

transition 组件

  • 用于给元素和组件添加进入/离开过渡
    • 条件渲染(v-if)
    • 条件展示(v-show)
    • 动态组件
    • 组件根节点
  • 组件提供了6个 class 用于设置过渡的具体效果
    • 进入的类名
      • v-enter
      • v-enter-to
      • v-enter-active
    • 离开的类名
      • v-leave
      • v-leave-to
      • v-leave-active
<transition>
  <p v-if="showDemo"></p>
</transition>
<!-- =================== -->
<style>
  .v-enter-active, .v-leave-active {
    transition: all .5s;
  }
  .v-enter, .v-leave-to {
    opacity: 0;
  }
</style>

transition 组件的相关属性

给组件设置 name 属性,可以用于给多个元素、组件设置不同的过渡效果,这时需要将 v- 更改为对应的 name- 的形式

例如:
<transiton name="demo"> 的对应类名前缀为:demo-enertdemo-leave

<transition name="demo">
  <p v-if="showDemo"></p>
</transition>
<!-- =================== -->
<style>
  .demo-enter-active, .demo-leave-active {
    transition: all .5s;
  }
  .demo-enter, .demo-leave-to {
    opacity: 0;
  }
</style>

通过 appear 属性,可以让组件在初始渲染时实现过渡

<transition appear>
  <p v-if="showDemo"></p>
</transition>

自定义过渡类名

自定义类名比普通类名优先级更高,在使用第三方 CSS 动画库时非常有用

  • 用于设置自定义过渡类名的属性如下:
    • enter-…
      • enter-class
      • enter-active-class
      • enter-to-class
    • leave-…
      • leave-class
      • leave-active-class
      • leave-to-class
    • appear-…
      • appear-class
      • appear-to-class
      • appear-active-class
<transition
  enter-active-class = "test"
  leave-active-class = "test"
>
  <p v-if="showDemo"></p>
</transition>
<!-- =================== -->
<style>
  .v-enter-active, .v-leave-active {
    transition: all .5s;
  }
  .v-enter, .v-leave-to {
    opacity: 0;
  }
  .test {
    transition: all 3s;
  }
</style>

Animate.css 是一个第三方 CSS 动画库,通过设置类名来给元素添加各种动画效果

<transition
  enter-active-class = "animate_bounceInDown"
  leave-active-class = "animate_bounceOutDown"
>
  <p v-if="showDemo"></p>
</transition>
  • 使用注意:
    • animate_ 前缀与 compat 版本
    • 基础类名 animated

transition-group 组件

  • <transition-group> 用于给列表统一设置过渡动画
    • tag 属性用于设置容器元素,默认为<span>
    • 过渡会应用于内部元素,而不是容器
    • 子节点必须有独立的 key 动画才能正常工作

当列表元素变更导致元素位移,可以通过 .v-move 类名设置移动时的效果

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    ul {
      position: relative;
    }

    .v-enter, .v-leave-to {
      opacity: 0;
      transform: translateX(100px);
    }

    .v-enter-active, .v-leave-active {
      transition: all .5s;
    }

    /* 让元素在离场的过程中脱离标准流 */
    .v-leave-active {
      position: absolute;
    }

    .v-move {
      transition: all .5s;
    }

  </style>
</head>
<body>
  <div id="app">
    <input type="text"
      v-model="newTitle"
      @keyup.enter="addItem"
    >

    <transition-group
      tag="ul"
    >
      <li
        v-for="item in items"
        :key="item.id"
        @click="removeItem(item)"
      >
        {{ item.title }}
      </li>
    </transition-group>
  </div>  
  <script src="./lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        items: [
          { id: 1, title: '示例内容1'},
          { id: 2, title: '示例内容2'},
          { id: 3, title: '示例内容3'},
          { id: 4, title: '示例内容4'},
          { id: 5, title: '示例内容5'},
        ],
        newTitle: '',
        latestId: 5
      },
      methods: {
        addItem () {
          this.items.push({
            id: this.latestId + 1,
            title: this.newTitle
          });
          this.latestId++;
          this.newTitle = '';
        },
        removeItem (item) {
          var i = this.items.indexOf(item);
          this.items.splice(i, 1);
        }
      }
    });
  </script>
</body>
</html>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于Vue.js组件巨详细的一篇文章 的相关文章

  • js 数组id去重

    可以用下面的方法来去除数组中的重复项 先将数组转换为 Set 类型 然后再转回数组 这种方法的缺点是会丢失原数组的顺序 const arr 1 2 3 3 2 1 const unique new Set arr console log u

随机推荐

  • C语言PTA题目:7-22 1022 利息

    输入存款金额money 存期year和年利率rate 根据下列公式计算存款到期时的利息interest 税前 输入格式 输入可能有多行 每行有3个整数 分别表示金额 存期 年 年利率 百分比数 输出格式 根据money 1 rate yea
  • 服务器怎么把自己的项目放上去,怎么把项目放到云服务器上

    怎么把项目放到云服务器上 内容精选 换一换 云服务器组是对云服务器的一种逻辑划分 云服务器组中的弹性云服务器遵从同一策略 当前仅支持反亲和性 即同一云服务器组中的弹性云服务器分散地创建在不同的主机上 提高业务的可靠性 您可以使用云服务器组将
  • 微信小程序:字体保持大小

    小程序和网页差不多 前台用wxml把内容摆好 然后用css调整样式 所以和web一样 必须要能够精确控制每一个元素的大小 在Web中 通过CSS基本达到了像素级的控制 但在小程序中 情况有所不同 下面是我通过微信提供的事件分析 把近7天访问
  • 数字化转型方法论汇总(学习笔记)

    数字化转型方法论汇总 德勤制造业数字化转型方法论 数字化转型的3大要点 1 从满足利益相关者期望出发 2 以企业价值引领业务模式创新 3 以信息作为企业神经中枢 重塑组织协同 一 关注集团利益相关者 两类利益相关者 集团外部的证监会 国资委
  • 比较2个数组是否一样

    需求 如果两个数组的类型 元素个数 元素顺序和内容是一样的我们就认为这2个数组是一模一样的 请使用方法完成 能够判断任意两个整型数组是否一样 并返回true或者false 分析 1 定义方法 接收2个整型数组 gt 是否需要参数 返回值类型
  • 《Win10——如何进入高级启动选项》

    Win10 如何进入高级启动选项 第一种方法 1 管理员命令提示符输入如下代码 自动重启并进入高级启动选项 shutdown r o f t 00 第二种方法 1 管理员命令提示符输入以下代码 开机时按下F8 进入高级启动选项 bcdedi
  • java基础总结(二十五)--访问修饰符protected

    三 protected 关键字的真正内涵 很多介绍Java语言的书籍 包括 Java编程思想 都对protected介绍的比较的简单 基本都是一句话 就是 被protected修饰的成员对于本包和其子类可见 这种说法有点太过含糊 常常会对大
  • 基于python 自写Tobii VI-T滤波器

    文章目录 官网参考文档 Gap fill in interpolation Eye selection Noise reduction Velocity calculator I VT classifier Merge adjacent f
  • react-router-dom V6

    目录 1 前言 2 变更概览 将 Switch 升级为 Routes 路由匹配组件参数 由 component 改为 element 相对路径识别 子路由不需要补全父路由的path react会自动补全 用 useNavigate 替代 u
  • web开发编码_编码和游戏开发

    web开发编码 As a game enthusiast and a beginner programmer I always wonder what it would be like to develop a game 作为游戏发烧友和初
  • 入门接口测试

    首先 什么是接口呢 接口一般来说有两种 一种是程序内部的接口 一种是系统对外的接口 系统对外的接口 比如你要从别的网站或服务器上获取资源或信息 别人肯定不会把数据库共享给你 他只能给你提供一个他们写好的方法来获取数据 你引用他提供的接口就能
  • gcc 若干安全相关选项

    1 FORTIFY SOURCE buffer over flow 防御 参考 http fedoraproject org wiki Security Features Compile Time Buffer Checks 28FORTI
  • Elasticsearch8.2扩容挪数据master出现异常

    背景 1 ES 8 2 版本集群 从10节点扩到20节点 变更 目标替换老的10个节点 先扩容新节点再下掉老节点 2 挪数据执行exclude API 排除老节点IP 设置迁移速率为800Mb s 默认40Mb s 异常 1 迁移过程中突然
  • python笔记第四章---选择结构

    一 程序的组织结构 fact 任何简单或复杂的算法都可以由顺序结构 选择结构和循环结构这三种基本结构组合而成 顺序结构 计算机的流程控制 选择结构 if语句 循环结构 while语句 for in语句 1 顺序结构 程序从上到下顺序的执行代
  • Linux文件权限的设置

    本文章主要介绍了对Linux文件的权限以及如何设置权限 一 查看文件的权限与属性 ls l 或者 ll查看文件属性 二 可以列出如下图所示的一些信息 rw r r 第一位代表文件类型 d 表示目录 l 表示链接文件 表示普通文件 b 表示快
  • Postman测试webService接口

    1 打开Postman界面如下 设置Content Type text xml 2 设置body 3 请求结果如下 4 至此通过Postman进行webService接口测试测试完毕
  • 使用过滤器和request装饰增强来彻底解决乱码问题

    在客户端以get或者post方式提交数据时 可能会出现客户端与服务端编码集不匹配而发生乱码的现象 在对post方式产生的乱码我们可以用 request setCharacterEncoding utf 8 语句来解决 在对get方式产生的乱
  • maven&​ Plugin ‘org.apache.tomcat.maven:tomcat7-maven-plugin:2.2’ not found​报错解决【问题及解决过程记录】

    目录 什么是 Maven 安装 解压后需要配置环境变量 在path新增路径 验证maven安装成功 Win R打开cmd 输入mvn v 在配置文件中设置本地仓库路径 maven仓库的种类和关系 编辑 maven目录结构 编辑 maven的
  • oracal从入门到精通(一)

    1 1了解最新版本Oracle 11g 可以在Oracle的官方网站www oracle com获取Oracle的版本信息 本书中要讲解的是Oracle 11g的第1版 所以在这里只对Oracle 11g的各版本做以说明 Oracle 11
  • 关于Vue.js组件巨详细的一篇文章

    文章目录 Vue js 组件 全局注册 组件基础 组件命名规则 template 选项 data 选项 局部注册 组件通信 父组件向子组件传值 props 命名规则 单项数据流 props 类型 props 验证 非 props 属性 子组