React -> Vue Comparison

import CoreConcept from './CoreConcept.jsx';
import { CORE_CONCEPTS } from '../data.js';

export default function CoreConcepts() {
return (
<section id="core-concepts">
<h2>Core Concepts</h2>
<ul>
{CORE_CONCEPTS.map((conceptItem) => (
<CoreConcept key={conceptItem.title} {...conceptItem} />
))}
</ul>
</section>
);
}
import CoreConcept from './CoreConcept.jsx';
import { CORE_CONCEPTS } from '../data.js';

export default function CoreConcepts() {
return (
<section id="core-concepts">
<h2>Core Concepts</h2>
<ul>
{CORE_CONCEPTS.map((conceptItem) => (
<CoreConcept key={conceptItem.title} {...conceptItem} />
))}
</ul>
</section>
);
}
<template>
<section id="core-concepts">
<h2>Core Concepts</h2>
<ul>
<CoreConcept
v-for="concept in CORE_CONCEPTS"
:key="concept.title"
v-bind="concept"
/>
</ul>
</section>
</template>

<script setup>
import CoreConcept from './CoreConcept.vue'
import { CORE_CONCEPTS } from '../data.js'
</script>
<template>
<section id="core-concepts">
<h2>Core Concepts</h2>
<ul>
<CoreConcept
v-for="concept in CORE_CONCEPTS"
:key="concept.title"
v-bind="concept"
/>
</ul>
</section>
</template>

<script setup>
import CoreConcept from './CoreConcept.vue'
import { CORE_CONCEPTS } from '../data.js'
</script>
22 Replies
Rägnar O'ock
Rägnar O'ock20h ago
what does data.js look like ?
CDL
CDLOP20h ago
for the CoreConcepts object it's
export const CORE_CONCEPTS = [
{
image: componentsImg,
title: 'Components',
description:
'The core UI building block - compose the user interface by combining multiple components.'
},
{
image: jsxImg,
title: 'JSX',
description:
'Return (potentially dynamic) HTML(ish) code to define the actual markup that will be rendered.'
},
export const CORE_CONCEPTS = [
{
image: componentsImg,
title: 'Components',
description:
'The core UI building block - compose the user interface by combining multiple components.'
},
{
image: jsxImg,
title: 'JSX',
description:
'Return (potentially dynamic) HTML(ish) code to define the actual markup that will be rendered.'
},
Rägnar O'ock
Rägnar O'ock20h ago
hum, you've found yourself in one of the very few instances where v-bind: can be usefull...
CDL
CDLOP20h ago
hahaha I was only aware of :id :class to be honest, I didn't think v-bind was used outside of that
Rägnar O'ock
Rägnar O'ock20h ago
tho, for readability I would advise you to do something like :
<CoreConcept
v-for="{image, title, description} in CORE_CONCEPTS"
:key="title"
:image
:title
:description
/>
<CoreConcept
v-for="{image, title, description} in CORE_CONCEPTS"
:key="title"
:image
:title
:description
/>
that way it's both easier to see what is in CORE_CONCEPTS and you don't risk having weird error when you add something else in your data.js or rename something (and you should avoid using id= in components unless you need some outside code to access it, it will cause problems if you get to reuse your component)
CDL
CDLOP20h ago
ah sure, that makes sense, similar visual to
export default function CoreConcept({ title, image, description }) {
return (
<li>
<img src={image} alt={title} />
<h3>{title}</h3>
<p>{description}</p>
</li>
);
}
export default function CoreConcept({ title, image, description }) {
return (
<li>
<img src={image} alt={title} />
<h3>{title}</h3>
<p>{description}</p>
</li>
);
}
Rägnar O'ock
Rägnar O'ock20h ago
yeah well... yes and no yes in the sense that both use destructuring no in the sens that one is the component's usageand the other is the component's definition
CDL
CDLOP19h ago
yeah meant the destructuring I'm a wee bit confused on this part.. how is variantImage working with variant.image?
<script setup>
import { ref } from 'vue';
import socksGreenImage from './assets/images/socks_green.jpeg';
import socksBlueImage from './assets/images/socks_blue.jpeg';

const product = ref('Socks');
const image = ref(socksGreenImage);
const inStock = true;

const details = ref(['50% cotton', '30% wool', '20% polyester']);

const variants = ref([
{ id: 2234, color: 'green', image: socksGreenImage },
{ id: 2235, color: 'blue', image: socksBlueImage }
]);

const cart = ref(0);

const addToCart = () => {
cart.value += 1;
};

const updateImage = (variantImage) => {
image.value = variantImage;
};
</script>

<template>
<div class="nav-bar"></div>
<div class="cart">Cart({{ cart }})</div>
<div class="product-display">
<div class="product-container">
<div class="product-image">
<img v-bind:src="image" />
</div>
<div class="product-info">
<h1>{{ product }}</h1>
<p v-if="inStock">In Stock</p>
<p v-else>Out of Stock</p>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<div v-for="variant in variants" :key="variant.id" @mouseover="updateImage(variant.image)">
{{ variant.color }}
</div>
<button @click="addToCart" class="button">Add to Cart</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import socksGreenImage from './assets/images/socks_green.jpeg';
import socksBlueImage from './assets/images/socks_blue.jpeg';

const product = ref('Socks');
const image = ref(socksGreenImage);
const inStock = true;

const details = ref(['50% cotton', '30% wool', '20% polyester']);

const variants = ref([
{ id: 2234, color: 'green', image: socksGreenImage },
{ id: 2235, color: 'blue', image: socksBlueImage }
]);

const cart = ref(0);

const addToCart = () => {
cart.value += 1;
};

const updateImage = (variantImage) => {
image.value = variantImage;
};
</script>

<template>
<div class="nav-bar"></div>
<div class="cart">Cart({{ cart }})</div>
<div class="product-display">
<div class="product-container">
<div class="product-image">
<img v-bind:src="image" />
</div>
<div class="product-info">
<h1>{{ product }}</h1>
<p v-if="inStock">In Stock</p>
<p v-else>Out of Stock</p>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<div v-for="variant in variants" :key="variant.id" @mouseover="updateImage(variant.image)">
{{ variant.color }}
</div>
<button @click="addToCart" class="button">Add to Cart</button>
</div>
</div>
</div>
</template>
ah.. because you set image to the value of variantImage, ignore me. and then you use it here
@mouseover="updateImage(variant.image)
@mouseover="updateImage(variant.image)
because it's using the parameter
const updateImage = (variantImage) => {
const updateImage = (variantImage) => {
Rägnar O'ock
Rägnar O'ock19h ago
yeah, it's just a function call no magic happening here
CDL
CDLOP19h ago
ya how odd, first time I've encountered something forcing me to use ' ' and not " " (naturally find " " easier)
<img :class="{ 'out-of-stock-img': !inStock }" v-bind:src="image" />
<img :class="{ 'out-of-stock-img': !inStock }" v-bind:src="image" />
Rägnar O'ock
Rägnar O'ock19h ago
it's a personal taste, but I like using simple quotes '' in JS/TS and double quotes "" with HTML for this exact reason
Rägnar O'ock
Rägnar O'ock18h ago
'cause the whole code is encoded in it
CDL
CDLOP18h ago
lmao I couldn't figure out how to turn add vue to codepen
Rägnar O'ock
Rägnar O'ock18h ago
just... use the provided template...
Rägnar O'ock
Rägnar O'ock18h ago
avoid using disabled on buttons, it's bad for a11y (it's as if you had display: none on it) use aria-disabled="true" instead. other than that it's nice could use a bit of // #region in the script to group up the related stuff, but overall it's good (you might also wantto replace that v-on:click by @click
CDL
CDLOP18h ago
Forgot about the aria-disabled! I'm stumped on this part, and google sucked at helping..
const onSale = ref(true)
const onSale = ref(true)
whilst that's true, I need a message to appear showing "brand + product is on sale" which I think is something such as....
const saleMessage = computed(() => {
return onSale.value + ' ' + product.value + ' ' + "is on sale"
})
const saleMessage = computed(() => {
return onSale.value + ' ' + product.value + ' ' + "is on sale"
})
with
<p v-if="onSale">{{ saleMessage }}</p>
<p v-if="onSale">{{ saleMessage }}</p>
However... how do I get it to check whether onSale is true or false lol
Rägnar O'ock
Rägnar O'ock18h ago
what do you mean ?
CDL
CDLOP18h ago
oh hold on I think I'm just being dumb
Rägnar O'ock
Rägnar O'ock18h ago
might be that
CDL
CDLOP18h ago
my computed property isn't checking the value of onSale, but my v-if is, I guess That's enough of that for 1 night, that was very refreshing though!

Did you find this page helpful?