简体   繁体   中英

Vue.js - Is there a more elegant way to conditionally apply class?

I have the following vue instance which has a method to conditionally return some html markup. As you can see the markup is identical for each condition, only different styles are being applied.

Is there a more elegant way to achieve the same? Also should I be using a method or a computed property or a component to achieve this - If I should use a computed property how to I pass the value to evaluate ?

Any one know any other way?

<div v-for="item in items">
    <div v-if="!_.isEmpty(item.files)">
        <ul >
            <li v-for="file in item.files">
                <span v-html="fileIcon(file.fileExtension)"></span>
            </li>
        </ul>
   </div>
</div>


 var vm =  new Vue({
        el: '#root',
        data: {
           items: [
                    {
                      "id": 126,
                      "content": "blah...",
                      "files": [
                           {
                              "id": 8,
                              "filename": "test.doc",
                              "fileExtension": "doc"
                           }
                       ]
                    },
                    {
                      "id": 127,
                      "content": "blah...",
                      "files": []
                    }
            ]
         },
         methods: {
            fileIcon: function (extension) {

                var str;

                switch (extension)
                {
                    case "jpg":
                    case "jpeg":
                    case "png":
                    case "gif":
                        str = "<i class='fa fa-file-image-o file-picture'></i>";
                        break;
                    case "pdf":
                        str = "<i class='fa fa-file-pdf-o file-pdf' ></i>";
                        break;
                    case "xls":
                    case "xlsx":
                        str = "<i class='fa fa-file-excel-o file-excel' ></i>";
                        break;
                    case "doc":
                    case "docx":
                        str = "<i class='fa fa-file-word-o file-word' ></i>";
                        break;
                    default:
                        str = "<i class='fa fa-file-file-o file-empty' ></i>";
                        break;
                }

                return str;
            }

        }
 });

Please note I'm very new to Vue so some code snippet to guide would be appreciated.

I don't think you need/should use v-html for something like this.

You just need to set up a map to link type to class

define the object

let icons = {
  jpg: ['fa-file-image-o', 'file-picture'],
  jpeg: ['fa-file-image-o', 'file-picture'],
  png: ['fa-file-image-o', 'file-picture'],
  gif: ['fa-file-image-o', 'file-picture'],
  pdf: ['fa-file-pdf-o', 'file-pdf'],
  xls: ['fa-file-excel-o', 'file-excel'],
  xlsx: ['fa-file-excel-o', 'file-excel'],
  doc: ['fa-file-word-o', 'file-word'],
  docx: ['fa-file-word-o', 'file-word']
}

create a method

fileIcon (type) {
  return icons[type] || ['fa-file-file-o', 'file-empty']
}

then call it in the template <span :class="fileIcon(file.fileExtension)">

You can use methods to return classes, see this codepen:

https://codepen.io/huntleth/pen/POdGRL

See here for more info: https://v2.vuejs.org/v2/guide/class-and-style.html

Ideally, you would store the file types and their corresponding classes in data as well, this would reduce complexity of the method.

 var vm = new Vue({ el: '#app', data: { items: [ { "id": 126, "content": "blah...", "files": [ { "id": 8, "filename": "test.doc", "fileExtension": "doc" } ] }, { "id": 127, "content": "blah...", "files": [] } ] }, methods: { fileIcon: function (file) { var ext = file.fileExtension; var str; switch (ext) { case "jpg": case "jpeg": case "png": case "gif": str = "fa fa-file-image-o file-picture"; break; case "pdf": str = "fa fa-file-pdf-o file-pdf"; break; case "xls": case "xlsx": str = "fa fa-file-excel-o file-excel"; break; case "doc": case "docx": str = "fa fa-file-word-o file-word"; break; default: str = "fa fa-file-file-o file-empty"; break; } return str; } } });
 <div id="app"> <div v-for="item in items"> <div v-if="!_.isEmpty(item.files)"> <ul > <li v-for="file in item.files"> <i :class="fileIcon(file)">{{file.filename}}</i> </li> </ul> </div> </div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM