第一个Vue程序

说明

《Vue开发实战-从0开始搭建大型Vue项目》是 Ant Design Vue 的作者在极客时间开的一门视频课,笔者记录一下学习笔记,仅供参考。

组件

我们通常把可拆分的html,以及拆分后的逻辑,样式组合在一起称之为组件。

通过一个例子了解一下:一个简单的TodoList项目代码如下:

<div id="app">
    <ul>
        <li>
            <input type="checkbox">
            <span>学习 Vue 属性span>
            <button>删除button>
        li>
        <li>
            <input type="checkbox">
            <span>学习 Vue 事件span>
            <button>删除button>
        li>
        <li>
            <input type="checkbox">
            <span>学习 Vue 插槽span>
            <button>删除button>
        li>
    ul>
div>

看到上面的代码,我们可以把li标签独立出来。

在Vue中,通过Vue.component定义(注册)一个组件:

1、起名:‘todo-item’

2、template:写上html

Vue.component('todo-item', {
    template: `
  • 学习 Vue 插槽
  • `
    })

    3、组件使用:

    <div id="app">
        <ul>
            <todo-item>todo-item>
            <todo-item>todo-item>
            <todo-item>todo-item>
        ul>
    div>
    

    4、需提供挂载点

    // 首先我们new Vue 一个实例,提供一个挂载点
    new Vue({
        el: '#app'
    })
    

    关于缺失的学习 Vue 插槽,学习 Vue 事件,就需要用到Vue的属性。

    属性

    加载组件时,我们同样可以传递不同的参数(属性),组件也可以接受参数(属性)来显示不同的内容。

    <div id="app">
        <ul>
            <todo-item item="学习 Vue 属性">todo-item>
            <todo-item item="学习 Vue 事件">todo-item>
            <todo-item item="学习 Vue 插槽">todo-item>
        ul>
    div>
    
    Vue.component('todo-item', {
        // 声明能接收的参数(属性)
        props: ['item'],
        // {{item}} 使用传递过来的 item
        template: `
  • {{item}}
  • `
    })

    精简一下代码:

    <div id="app">
        <ul>
            <todo-item
                v-for="item in list"
                :item="item"
            >
            todo-item>
        ul>
    div>
    <script>
        new Vue({
            el: 'app',
            data() {
                return {
                    list: [
                        '学习 Vue 属性',
                        '学习 Vue 事件',
                        '学习 Vue 插槽'
                    ]
                }
            }
        })
    script>
    

    事件

    那么怎么删除?

    vue提供了一个简单的方式进行绑定事件

    就是使用@xxx就可以进行事件绑定

    Vue.component('todo-item', {
        props: ['item'],
        // 使用@click="xxx"
        template: `
  • {{item}}
  • `
    , methods: { handleClick() { // vue提供了一个api,让子组件发射事件给父组件,父组件通过@delete方式来绑定接收delete事件 this.$emit("delete", this.item) } } })
    
    <todo-item
        v-for="item in list"
        :item="item"
        @delete="handleDelete"
    >
    todo-item>
    

    最后在父组件methods上面定义一个handleDelete方法去改变list数组就可以完成删除操作。

    new Vue({
        el: 'app',
        data() {
            return {
                list: [
                    '学习 Vue 属性',
                    '学习 Vue 事件',
                    '学习 Vue 插槽'
                ]
            }
        },
        methods: {
            handleDelete(item) {
                /**
                * findIndex用法
                * 1、findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
                * 2、findIndex() 方法为数组中的每个元素都调用一次函数执行:
                *  1)、当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。
                *  2)、如果没有符合条件的元素返回 -1
                *
                * 注意:
                * 1、findIndex() 对于空数组,函数是不会执行的。
                * 2、findIndex() 并没有改变数组的原始值。
                */
                const index = this.list.findIndex(text=>text === item)
                this.list.splice(index, 1)
            }
        }
    })
    

    插槽

    1、默认插槽:

    比如想让todolist中的学习 Vue XXX前加个图标icon,怎么办?

    我们不能通过属性传递这些带有标签的内容,而是通过一种名叫插槽的东西进行传递。

    <todo-item
        v-for="item in list"
        :item="item"
        @delete="handleDelete"
    >
        <span>我是Iconspan>
    todo-item>
    

    同时也不能用{{}}来解析,我们需要使用 写法来解析:

    Vue.component('todo-item', {
        props: ['item'],
        // 添加 下面这种称之为默认插槽
        template: `
  • {{item}}
  • `
    , methods: { handleClick() { this.$emit("delete", this.item) } } })

    2、具名插槽:

    如果需要加两个图标,一个前,一个后,怎么处理?

    这时需要我们添加name,称之为具名插槽。

    <todo-item
        v-for="item in list"
        :item="item"
        @delete="handleDelete"
    >
        <span slot="prefixIcon">我是前缀Iconspan>
        <span slot="suffixIcon">我是后缀Iconspan>
    todo-item>
    

    同样template需要添加:

    Vue.component('todo-item', {
        props: ['item'],
        template: `
  • {{item}}
  • `
    , methods: { handleClick() { this.$emit("delete", this.item) } } })

    3、作用域插槽:

    如果我们想通过input checkbox的选中与否来改变图标的颜色,该怎么做?

    1、先记录input checkbox的选中状态,我们使用Vue的v-model进行input的双向绑定:

    Vue.component('todo-item', {
        props: ['item'],
        data() {
            return {
                checked: false // 默认不选中
            }
        },
        template: `
  • {{item}}
  • `
    , methods: { handleClick() { this.$emit("delete", this.item) } } })

    2、状态有了,把这个状态传递给上层:

        <slot name="prefixIcon" v-bind="{checked}">slot>
    

    3、接收到状态后,控制样式

    <span
        slot="prefixIcon"
        slot-scope="props"
        :style="{color: props.checked ? 'red' : 'blue'}"
    >
        我是前缀Icon
    span>
    

    todolist代码

    <html>
    
    <head>
        <style>
            .item {
                color: red;
            }
        style>
    head>
    
    <body>
        <div id="app">
            {{msg}}
            <div>
                <input type="text" v-model="info">
                <button @click="handleClick">添加button>
            div>
            <ul>
                <todo-item v-for="item in list" :item="item">todo-item>
            ul>
        div>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
        <script>
            Vue.component('todo-item', {
                props: ['item'],
                template: '
  • {{item}}
  • '
    }) new Vue({ el: '#app', data() { return { msg: 'hello vue!', info: '', list: [], } }, methods: { handleClick() { this.list.push(this.info) this.info = '' } } })
    script> body> html>

    你可能感兴趣的:(07-Vue)