コンポーネントが人生を変える_Vue の謎を解き明かすコンポーネント_html/css_WEB-ITnose

WBOY
リリース: 2016-06-21 08:49:44
オリジナル
1468 人が閲覧しました

このセクションでは、Vue のコンポーネントについて学び、コンポーネントがどのように機能するかを理解し、一連の例を使用して、コンポーネントベースの考え方を使用してプロジェクトを開発すると、異なる感覚が得られることを証明します。 Vue のコンポーネント化のアイデアを理解していれば、このアイデアを使用して、ユーザーがコメントを投稿し、他のユーザーが任意のコメントに対して「はい」または「いいえ」を投票できるシステムを構築できます。

Vue に初めて触れる場合は、私の以前の記事「Vue をゼロから学ぶ」を読んで、Vue の基本的な構文を理解してください。

コンポーネントについて

コンポーネントを使用すると、構築している複雑なインターフェイスを持つアプリケーションを非常に適切に分離できます。同時に、コンポーネントは、パッケージ化して再利用することもできますが、再利用性も高くなります。開発中のさまざまなプロジェクトで。

まず単純な HTML ページを作成し、Vue をインスタンス化して DOM 要素にマウントします。

<!DOCTYPE html>      <html>            <head>                  <title>揭开Vue组件的神秘面纱</title>            </head>      <body>            //这中间就是实例挂载点的实例边界            <div id="vueInstance"></div>            //Vuw的CDN,之后会省略不写            <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>            <script>                  // 创建一个新的Vue实例,并设置挂载点                  var V = new Vue({                        el : '#vueInstance'                  });            </script>      </body></html>
ログイン後にコピー

「ゼロから Vue を学ぶ」の基本が準備できたので、最初のシンプルで再利用可能なコンポーネントを作成します。 Vue では、Vue.component() を使用してコンポーネントを作成および登録できます。このコンストラクターには 2 つのパラメーターがあります:

  • コンポーネントの名前

  • コンポーネント パラメーターを含むオブジェクト

このオブジェクトは、Vue() コンストラクターのオブジェクトに少し似ており、Vue() のオブジェクトにも似ています。 ) el 属性と data 属性ですが、少し異なります。

Vue() コンストラクターの el と data はオブジェクトにすることができます。 Vue.component() コンストラクターの el と data は関数のみにすることができます。

次に、最初のコンポーネントがどのように機能するかを見てみましょう。コンポーネントを登録し、pタグを使って自己紹介文を一行出力したいと考えています。そこでコンポーネントを作成し、2 つのパラメーターを入力しました:

  • コンポーネントの名前: 'mine'

  • 含まれるコンポーネント パラメーター オブジェクト: このオブジェクトにはプロパティ 'template' が含まれています。

Vue.component('mine',{    template : '<p>My name is Appian.</p>'})
ログイン後にコピー

これで、アプリケーションのどこでも使用できる独自のコンポーネントが完成しました。その一意の識別子 (コンポーネント名) を呼び出し、それを などの通常の HTML タグの形式で記述する限り、コンポーネントに登録されているコンテンツは次の場所に挿入されます。カスタムタグの場所。

 <div id="vueInstance">    <mine></mine>   //标识注册的内容会在这里插入    <mine></mine>    <mine></mine>   //重复插入注册内容 </div> <script>       Vue.component('mine',{   //这里就是注册的内容           template : '<p>My name is Appian.</p>'       });       var V = new Vue({             el : '#vueInstance'       }); </script>
ログイン後にコピー

Vue はテンプレートを使用してコンポーネントを置き換え、HTML タグを使用してカスタムの一意の識別子を DOM 構造に挿入して、HTML をより簡潔、すっきり、直感的にします。

複雑なコンポーネントを処理するにはテンプレート タグを使用します

ここで、私が作成したコンポーネントに p タグが 1 行しかないのはなぜだろうと考えているかもしれません。 p タグの行に必要なコンポーネントを用意するのはそんなに面倒ですか?はい、コンポーネントはより複雑なカプセル化と再利用のために作成されます。したがって、Vue.component() コンストラクターの template 属性で HTML コードのみを定義し、文字列連結を使用してすべてのコードを記述する場合は、jq を使用するよりもさらに疲れ果てるだけです。

上記の状況を回避するために、テンプレート タグ (属性とタグは異なることに注意してください) を使用して目的を達成できます。ページ上の任意の場所にテンプレート タグを定義し、テンプレート タグ内にテンプレートを記述することができます。ページの読み込み時にはテンプレート タグは表示されないため、このタグのコンテンツは必要な場合にのみ表示されます。したがって、テンプレート タグを任意の場所に配置して ID を指定すると、コンポーネントの登録時にテンプレートを見つけることができます。

 <div id="vueInstance">    <mine></mine>   //标识注册的内容会在这里插入 </div> <template id="mineTpl">         <p>My name is Appian.</p>         <button>点击没有任何事件</button> </template> <script>       Vue.component('mine',{   //这里就是注册的内容           template : '#mineTpl'       });       var V = new Vue({             el : '#vueInstance'       }); </script>
ログイン後にコピー

このメソッドを使用して複雑なコンポーネントを作成できるようになりました。このようにして、複雑なコードを機能分割後にコンポーネントに分割し、コンポーネントの考え方を使用してコードの塊を回避できます。コンポーネント化により、モジュールをより明確に編成し、コンポーネントをより Vue らしくすることができます。

props を介してコンポーネントにデータを転送します

コンポーネント インスタンスが作成されるたびに、このインスタンスは独自のコンポーネント スコープを分割します。このスコープにより、このコンポーネント領域でその親を取得できなくなります。コンポーネントのデータ。では、Vue は親コンポーネントから子コンポーネントへのデータの受け渡しをどのように処理するのでしょうか?答えは、小道具によるものです。

親コンポーネントから子コンポーネントにデータを渡す最も単純な例を見てみましょう。登録された Mine コンポーネントは子コンポーネントであり、親コンポーネントから「city」データ情報を取得することを期待しているため、親コンポーネントによって渡された city 値を受け取るためにパラメーター props が Mine のコンストラクターに追加されます。

Vue.component('mine',{    template : '<p>Appian is from {{ city }}.</p>',    props : ['city']});
ログイン後にコピー

上記の例では、props を配列として定義したため、props を使用して複数のフィールドを受け取ることができ、これらのフィールドは子コンポーネントが親コンポーネントから期待するものです。

Props は配列である必要はなく、オブジェクトにすることもできます。多くの props 制限はオブジェクト内で詳細に定義できます。

Vue.component('mine',{    template : '<p>Appian is from {{ city }}.</p>',    props : {        city : {            type : String,//定义字符串类型            required : true,//该字段是必须的            default : 'China'//设置默认值        }    }});
ログイン後にコピー

我们不需要每次都将props的限制条件都写出来,因为在这个例子中的数据是一个很简单的字段,上例中只是为了完整展示props的对象表示方法,所以才展开来写的。

那父组件那里又是怎么指派字段给子组件的呢?

    <mine city="FuJian-YongAn"></mine>
ログイン後にコピー

这样直接在mine标签里面定义‘city’字段,就是父组件指派字段的方式之一。但是这样直接指派是很瞎的,我们需要的是动态变化的city,这个一会我们会说到的。

先简单介绍一下我们接下来要做的事。我们要假装我们正在搭一个博客,博客需要展示作者的基本信息,此时,我们可能会需要一些数据对象,可能是从数据库获得的,或者ajax请求到的,总之就是请求到了之后,将这个数据对象定义在父级的data中。并在html的template标签中准备渲染。

<div id="vueInstance">    <mine></mine> //标识注册的内容会在这里插入,之后也要展开来说!!!</div><template id="mineTpl">     <h1>{{ name }}</h1>     <h2>{{ title }}</h2>     <h3>{{ city }}</h3>     <p>{{ content }}</p></template><script>    //Vue.component()的构造在下文中展开来说!!!    var V = new Vue({         el : '#vueInstance',         data : {            name : 'Appian',            title : 'This is a title',            city : 'FuJian-XiaMen',            content : 'There are some desc about Appians Blog'         }    });</script>
ログイン後にコピー

准备好模板渲染之后,当然也要注册mine的构造器Vue.component()。除了基本的绑定模板id(#mineTpl)之外,还需要指定这个子组件想要的数据的字段名,并把期望得到的4个字段写在props中。

Vue.component('mine',{   template : '#mineTpl',   props : ['name','title','city','content']});
ログイン後にコピー

这样我们就能告诉父级,子组件需要的字段是哪些。接下来父级就可以指派字段的值给子组件了。前面的city字段是写死的,现在这里绑定的字段就是动态绑定的。

<mine :name='name'      :title='title'      :city='city'      :content='content'  ></mine>
ログイン後にコピー

等号左右两边的字段名称可以不一样。

等号左边的字段名,是指在子组件的props中声明的名字。在html写成肉串式,但是在props中写成驼峰式。

等号右边的字段名,是指在父级里定义的字段的名字。

‘:’是‘v-bind’的缩写

这样就能把父组件的4个字段绑定到子组件上。现在,只要父组件指派的字段的值一发生改变,子组件的值也会发生相应的改变。

构建一个简易评论社区系统

现在就可以利用前面学到的内容,搭建一个简易的评论社区系统,样式什么的先不管,只讲究js的具体实现。

  • 创建一个新的Vue实例

  • 给实例挂载一个div(#vueInstance)

  • 定义数据,然后渲染。

<div id="vueInstance">    <div class="container">        <ul>           //这里即将渲染出评论的投票列表        </ul>    </div></div><template id="postTpl">     <li>         <i class="up">我支持</i>         <span>票数: {{ post.votes }}</span>         <i class="down">我反对</i>         <a>话题: {{ post.title }}</a>       </li></template><script>    //Vue.component()的构造在下文中展开来说!!!    var V = new Vue({         el : '#vueInstance',         data : {             posts: [{                title: '请大大多多为我投票,我给大家发红包',                votes: 15             },{                title: '投我准没错',                votes: 53             },{                title: '不要投给我楼上的',                votes: 10             }]         }    });</script>
ログイン後にコピー

现在先构造好数据,有投票的话题和投票人数。然后再构造好模板(template标签),这个模板值用来渲染单个话题。模板里有除了渲染话题和投票人数,还有两个按钮,用来投赞成票或者反对票。之后我们只需要在html循环模板,然后就能多次插入模板,渲染成列表。当然也可以在模板里渲染好列表再一次插入。我们先用前一种方法。

不管css的样式问题,现在就可以开始注册Vue.component()构造器了,以便我们渲染页面。我们在注册的时候要明确,我注册的子组件需要的props是父级的posts数组中的一个元素对象post。所以我们应该这样注册:

Vue.component('post',{    template : '#postTpl',    props : ['post']});
ログイン後にコピー

然后我们使用自定义的标签插入在html中去。

<div id="vueInstance">    <div class="container">        <ul>           <post v-for="post in posts" :post="post"></post>        </ul>    </div></div>
ログイン後にコピー

这样我们就已经完成了循环输出posts数组了。因为我们把数组的元素指派给了子组件,所以子组件就可以渲染title和vote。接下来要做的就是增加“赞成”和“反对”按钮的逻辑代码,并我们需要对投票状态进行锁定,就是如果我们投了某个话题的赞成票就不能再投该话题的反对票,反之亦然。所以让我们开始在模板里面定义点击事件吧,投赞成票的事件叫做“upvote”,投反对票的事件叫做“downvote”。

<template id="postTpl">     <li>         <i class="up" @click="upvote">我支持</i>         <span>票数: {{ post.votes }}</span>         <i class="down" @click="downvote">我反对</i>         <a>话题: {{ post.title }}</a>       </li></template>
ログイン後にコピー
Vue.component('post',{    template : '#postTpl',    props : ['post'],    data : function (){        return {  //data必须为function,定义投票状态            upvoted: false,            downvoted: false        }    },    methods : {        upvote : function() { //点击赞成的事件            this.upvoted = !this.upvoted;            this.downvoted = false;        },        downvote: function() { //点击反对的事件            this.downvoted = !this.downvoted;            this.upvoted = false;        }    }});
ログイン後にコピー

注意,data里面的两个布尔值的定义是作为一个函数的返回值定义的。那是因为我们想要给每一个组件都设置一个是否投票的状态。

(还记得之前我说过,这次的列表渲染是循环渲染多个模板,每个模板都只是一个话题的相关信息,而现在在组件中定义的data:upvoted和downvoted,也是专属于某个模板的。)

这样我们如果投了某个话题的赞成票,并不会影响剩下话题的投票情况。

接下来已经完成了点击事件的状态控制,那么点击“赞成”和“反对”会导致话题的票数发生变化。这个时候我们可以利用之前的教程中学过的computed属性进行计算。

组件也有computed属性哦~

Vue.component('post',{    template : '#postTpl',    props : ['post'],    data : function (){ //同上,略 },    methods : {  //同上,略 },    computed: {  //重点部分        votes: function () {            if (this.upvoted) {                return this.post.votes + 1;            } else if (this.downvoted) {                return this.post.votes - 1;            } else {                return this.post.votes;            }        }    }});
ログイン後にコピー

到此为止,应该组件中的逻辑处理差不多完成了,现在要做的就是让我们在组件中修改的投票人数,能够在模板中渲染出来。因为我们现在的votes的值是在子组件中修改的,而一开始渲染的时候,我们的votes只是一味的接受父级传过来的值,所以,现在要把修改的值显示在模板上。所以模板变成了这样:

<template id="postTpl">     <li>         <i class="up" @click="upvote">我支持</i>         <span>票数: {{ votes }}</span>         <i class="down" @click="downvote">我反对</i>         <a>话题: {{ post.title }}</a>       </li></template>
ログイン後にコピー

现在我们的投票系统已经基本完成了。我们可能会希望我们的投票系统好看一点,直观一点。所以我们可以在按钮上绑定一些样式。比如当用户已经投了某个话题的赞成票或者反对票,就让这个按钮变成橙色。

.disabled {    color : orange;}
ログイン後にコピー

Vue是利用v-bind:class来进行样式绑定的,可以简写成一个‘:’。其绑定的内容是一个对象,对象里面是class的名字和class对应的状态。

了解更多样式绑定的信息点这里

<template id="postTpl">     <li>         <i class="up" @click="upvote" :class="{disabled: upvoted}">我支持</i>         <span>票数: {{ votes }}</span>         <i class="down" @click="downvote" :class="{disabled: downvoted}">我反对</i>         <a>话题: {{ post.title }}</a>       </li></template>
ログイン後にコピー

如果我们点击了某个话题的赞成按钮,则它的upvoted就会变成true,则disabled的样式就绑定到赞成按钮上去。如果点了该话题的反对按钮,则它的upvoted就会变成false,则disabled就不会绑定到赞成按钮上。以上就是模板最终的样子。

组件的复用性的利用

我们已经利用了我们对Vue的基本语法还有一些组件的基本操作,建立起了一个基本的话题投票系统。在教程的最后一部分,我们将看看,我们应该如何将这个投票系统组件进行复用。

复用的关键在于组件的命名,让你的命名能够复用。至少你在构建你的组件的时候,你要问自己,“是否其他地方也能用到这个组件?”

比如,在上面的例子中,posts的意思是,这个数据是从ajax的post请求过来的数据,为了便于理解,才取名为posts,为了让自己的组件名字一看就知道关联,所以把模板的id定义为#postTpl,tpl是template的简写,自定义标签的命名也是post。总之,就是这样的细节,不仅方便自己阅读,也方便其他人阅读你的代码。

现在我们的评论系统需要增加一个功能,就是增加一个发布评论的功能。就是增加了一个发布评论的区域(#commentBox)。

<div id="vueInstance">    <div class="container">        <ul>           <post v-for="post in posts" :post="post"></post>        </ul>        <div id="commentBox">            请输入评论内容并提交:            <input type="text" v-model="comment" @keyup.enter="postComment">            <button @click="postComment">提交评论</button>        </div>    </div></div>//模板渲染不变<script>//Vue.component()的注册不变。var V = new Vue({     el : '#vueInstance',     data : {         posts: [{            title: '请大大多多为我投票,我给大家发红包',            votes: 15         },{            title: '投我准没错',            votes: 53         },{            title: '不要投给我楼上的',            votes: 10         }],          comment: ''     },     methods: {         postComment: function() {             this.posts.push({               title: this.comment,               votes: 0             })             this.comment = '';         }     }});</script>
ログイン後にコピー

输入框用v-model绑定了comment字段,为了无论用户输入什么,在提交的时候都能获得他输入的值。当用户按回车或者点击提交按钮的时候都会触发postComment方法。这里的事件绑定一个是用的回车事件 @keyup.enter,还有一个点击事件@click。postComment方法就是把话题和投票为0的对象push进posts数组中去,Vue会将新的模板自动渲染出来。

这样一个可复用的组件就构造完成了,组件化会节省开发者的很多时间。组件是否复用,也要结合开发的实际需求而定。

后记

到此为止,你就已经能够掌握了Vue的组件的基本使用,组件通过props向下传递数据,通过使用