Skip to content

Instantly share code, notes, and snippets.

@michaelrambeau
Last active March 11, 2017 06:17
Show Gist options
  • Save michaelrambeau/d4406bc81f0f92445f8b0419e717f5b3 to your computer and use it in GitHub Desktop.
Save michaelrambeau/d4406bc81f0f92445f8b0419e717f5b3 to your computer and use it in GitHub Desktop.
Trying Vue.js

A basic example using a simple HTML page with some old-fashioned script tags (no ES6, no building process)

GOAL: display the list of projects from bestof.js.org

├── index.html
└── js
    ├── app.js
    ├── components.js

The application is mounted using new Vue({ data, el }) in app.js file

Components are registred using the following syntax

Vue.component('my-component', {
  props: [],
  data: () => {
  },
  methods: {},
  computed: {},
  template: ``,
``
/* globals Vue, _ */
function renderProjects (projects) {
const topics = parseTopics(projects)
console.log(topics);
// console.log(sortTopics(topics))
const app = new Vue({
data: {
projects,
topics: Object.keys(topics)
},
el: '#app'
})
}
function filterByTopic (topic) {
return (project) => {
return project.topics.includes(topic)
}
}
function filterByQuery (query) {
return (project) => {
const re = new RegExp(query, 'i')
if (re.test(project.name)) return true
return re.test(project.description)
}
}
function parseTopics (projects) {
const topics = _.flatten(projects
.map(project => project.topics))
return topics.reduce(
(acc, topic) => {
return Object.assign({}, acc, {
[topic]: acc[topic] ? acc[topic] + 1 : 1
})
},
{}
)
}
function sortTopics (topics) {
return Object.keys(topics)
.map(key => ({ name: key, count: topics[key] }))
.sort((a, b) => a.count > b.count ? -1 : 1)
.filter(item => !['javascript'].includes(item.name))
.filter(item => item.count > 1)
.map(item => `${item.count} ${item.name}`)
}
/* globals filterByQuery, filterByTopic */
Vue.component('project-card', {
props: ['project'],
template: `
<div class="project-card">
{{ project.name }} {{ project.stars }}
</div>'
`
})
Vue.component('project-list', {
props: ['projects'],
template: `
<div>
{{projects.length}}
<project-card v-for="project in projects" v-bind:project="project">
</project-card>
</div>
`
})
Vue.component('project-table-row', {
props: ['project'],
template: `
<tr class="project-table-row">
<td>{{ project.name }}</td>
<td>{{ project.stars }}</td>
<td>{{ project.description }}</td>
<td>
<div v-for="topic in project.topics">
{{ topic }}
</div>
</td>
</tr>'
`
})
Vue.component('project-table', {
props: ['projects'],
template: `
<div>
<h4>{{projects.length}} projects</h4>
<table>
<thead>
<tr>
<td>Project</td>
<td>Stars</td>
<td>Description</td>
<td>Topics</td>
</tr>
</thead>
<project-table-row v-for="project in projects" v-bind:project="project">
</project-table-row>
</table>
</div>
`
})
function getFilteredProjects (projects, topic, query) {
console.log('Search', query);
if (topic === '' && query === '') return projects
if (query !== '') return projects.filter(filterByQuery(query))
return projects.filter(filterByTopic(topic))
}
Vue.component('project-view', {
props: ['projects', 'topics'],
data: () => ({
query: '',
topic: ''
}),
methods: {
resetTopic () {
this.topic = ''
}
},
computed: {
sortedTopics () {
return this.topics.sort((a, b) => a > b ? 1 : -1)
},
filteredProjects () {
if (this.topic === '' && this.query === '') return this.projects
if (this.query !== '') return this.projects.filter(filterByQuery(this.query))
return this.projects.filter(filterByTopic(this.topic))
}
},
template: `
<div>
<input v-model="query" placeholder="search" />
<select v-model="topic">
<option value="">(All topics)</option>
<option v-for="topic in sortedTopics">{{ topic }}</option>
</select>
<button v-on:click="resetTopic">Reset</button>
<project-table v-bind:projects="filteredProjects"></project-table>
</div>
`
})
<head>
<title>Testing Vue</title>
<link rel="stylesheet" href="https://unpkg.com/awsm.css/dist/awsm.min.css">
<link href="https://fonts.googleapis.com/css?family=PT+Sans|PT+Serif:400,400i,700,700i&amp;subset=cyrillic" rel="stylesheet">
</head>
<body>
<script src="https://unpkg.com/vue@2.1.10/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<h1>Testing VueJS</h1>
<div id="app">
<project-view v-bind:projects="projects" v-bind:topics="topics"></project-view>
</div>
<script src="/js/app.js"></script>
<script src="/js/components.js"></script>
<script>
const url = 'https://bestofjs-api-dev.firebaseapp.com/projects.json'
fetch(url)
.then(r => r.json())
.then(json => renderProjects(json.projects))
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment