【Vue3从零开始-第一章】1-4 v-bind和component

550 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

前言

本篇内容是第一章vue语法的最后一篇,通过本篇内容,我们将大致了解vue中的v-bind指令和组件的一些概念。大家可以通过下面链接了解vue的其他语法基础。

【Vue3从零开始-第一章】1-1 Hello world和计数器

【Vue3从零开始-第一章】1-2 v-on和v-if指令

【Vue3从零开始-第一章】1-3 v-for和v-model指令

下面的内容将在1-3的代码基础上带大家一起学习。

v-bind

在前面的几篇内容里面,我们经常会用到{{}}这样的格式去显示动态值,那么{{}}是什么意思呢?为啥可以显示出动态的值呢?

  • 在vue里面,{{}}表示插值表达式,在表达式里面可以做一些简单的js操作,也可以动态渲染data方法里面的值

  • 1-3的代码中,我们知道了双向数据绑定,在数据绑定的时候,我们也会用到这样的插值表达式去动态显示input中绑定的值。

 Vue.createApp({
   data() {
     return {
       inputValue: ''
     }
   },
   template: `
    <div> 
       <input v-model="inputValue" /> 
       <div>{{inputValue}}</div>
    </div> `
 }).mount('#root');

如果我们要在button标签上面,当鼠标放到标签上时,会显示inputValue的值,也就是给标签上的某个属性绑定一个动态值,我们可以不可以直接这样写呢?

template: `
    <div>
        <input v-model="inputValue" />
        <button v-on:click="handleAddItem" title="inputValue">增加</button>
    </div>
`

8sa33-l5j2l.gif

在浏览器中打开后,我们发现按钮上的title属性显示的是一个字符串inputValue,那我们可不可以在title属性中使用上面说的插值表达式呢?

template: `
    <div>
        <input v-model="inputValue" />
        <button v-on:click="handleAddItem" title="{{inputValue}}">增加</button>
    </div>
`

2nrdy-35i2t.gif

  • 现在我们看到的是title属性直接显示了{{inputValue}}字符串,没有渲染出我们想要的效果,那么这时候我们就要用到一个新的指令: v-bind
  • 在使用v-bind时,不需要添加{{}}插值表达式的写法
template: `
    <div>
        <input v-model="inputValue" />
        <button v-on:click="handleAddItem" v-bind:title="inputValue">增加</button>
    </div>
`

4nlyu-1mfeg.gif

现在我们可以在浏览器中看到一个另类的双向数据绑定的效果了,也就是用v-binddata中的值动态绑定到标签的属性值中显示。

小结一下

  • {{}}插值表达式是在标签之间使用,且可以动态输出data中的值。
  • v-bind指令是在标签上使用,也可以动态输出data中的值。

component组件

组件的概念不仅仅在vue里面有效,在整个前端的发展中都是有效的。那什么是组件呢?

  • 组件就是一个页面上的一部分 下面的图片中显示的红色框和蓝色框都可以看做是一个又一个的组件

image.png

<li v-for="(item, index) of list">
    <div>
        <span>{{index}}</span>
        <span> - </span>
        <span>{{item}}</span>
    </div>    
</li>

在项目中,我们往往会在一个标签里面嵌套很多标签来渲染我们需要显示出来的内容,但是这样的标签太多了之后,就会显得页面很臃肿,那么我们就可以把一些公共的地方拆分出来,单独做成一个组件去渲染。

下面我们就把1-3中的TodoList代码拆分出来。

首先我们要给vue的实例取一个名字

const app = Vue.createApp()

为什么要取一个名字呢?因为我们要在这个app上去注册一些组件

app.component()

注册组件之后呢,也要给这个组件取一个名字todo-item,后面跟着一个对象描述了这个组件对应的内容

app.component('todo-item', {})

组件有了,我们就要将TodoList代码中的li标签拆分出来,然后开始写组件中的代码

const app = Vue.createApp({
    data(){
        return {
            inputValue: '',
            list: []
        }
    },
    methods: {
        handleAddItem(){
            this.list.push(this.inputValue)
            this.inputValue = ''
        }
    },
    template: `
        <div>
            <input v-model="inputValue" />
            <button v-on:click="handleAddItem">增加</button>
            <ul>
                <todo-item v-for="(item, index) of list" />
            </ul>
        </div>
    `
}).mount('#root');

app.component('todo-item', {
    template: '<div>hello world</div>'
})
  • 我们在vue实例app上注册了一个组件,这个组件的名字叫todo-item,然后将组件放到ul标签中渲染出来

image.png 但是这时候我们刷新页面会发现,浏览器的Console报错了,找不到app.component这个方法。

那是因为我们在vue实例之后直接就挂载到root上了,挂载之后再去注册组件,是找不到组件的,那么我们就要改一下注册和挂载的逻辑顺序了。

const app = Vue.createApp({
    data(){
        return {
            inputValue: '',
            list: []
        }
    },
    methods: {
        handleAddItem(){
            this.list.push(this.inputValue)
            this.inputValue = ''
        }
    },
    template: `
        <div>
            <input v-model="inputValue" />
            <button v-on:click="handleAddItem" v-bind:title="inputValue">增加</button>
            <ul>
                <todo-item v-for="(item, index) of list" />
            </ul>
        </div>
    `
});

app.component('todo-item', {
    template: '<div>hello world</div>'
});

app.mount('#root');

先注册一个vue实例,取名为app,然后在实例上注册一个组件todo-item,最后将实例挂载到root上渲染出来

chrome-capture (6).gif

一个组件里面,不仅包含了这个组件的DOM结构,还应该包含这个组件的数据和js逻辑,从上面的组件代码中可以看到,我们在DOM结构上直接写死了数据,那下面我们就写一下组件上动态的渲染。

app.component('todo-item', {
    data(){
        return {
            item: 'Hello Dell'
        }
    },
    template: '<div>{{item}}</div>'
});
  • 通过组件代码可以看出,组件里面的逻辑代码和vue实例里面的逻辑代码基本是一致的,都是通过data方法来定义动态的渲染值。

chrome-capture (7).gif 虽然组件已经动态渲染了data里面定义的值,但是不能每次都渲染同样的数据,应该让组件渲染vue实例中的list里面的每一项数据,那么我们就可以通过上面学到的v-bind指令来定义了。

<ul>
    <todo-item v-for="item of list" v-bind:content="item" />
</ul>
  • 在组件上绑定一个属性,这个属性的名字叫content,值是itemitem就是list中的每一项值
app.component('todo-item', {
    props: ['content'],
    template: '<div>{{content}}</div>'
});
  • vue实例中调用todo-item组件的时候,在组件上绑定了一个content的属性,那么组件上就要接收这个属性,在组件上用props接收一个叫content的属性值,并把这个属性值放到DOM中的插值表达式中渲染出来。

chrome-capture (8).gif

1-3中的例子中,我们还渲染了list的下标index,那么在组件中渲染出来也是需要从实例传给组件的,方法和上面的一样。

<ul>
    <todo-item v-for="(item, index) of list" v-bind:content="item" v-bind:index="index" />
</ul>
app.component('todo-item', {
    props: ['content', 'index'],
    template: '<div>{{index}} - {{content}}</div>'
});
  • 在调用todo-item组件的时候,同样绑定一个属性index,然后在组件中去接收index,同时用插值表达式渲染出来。

chrome-capture (9).gif

总结

在上面的例子中,我们都用到了v-bind指令来绑定一些属性值,同时也用到了组件和组件之间的传值的过程,有什么不明白的地方,可以在评论区留言讨论讨论哦~

本章节完,下章节继续哦!!!