vue创建组件和注册组件
While React.js has taken much of the attention during the latest wave of JavaScript frameworks, Vue.js has quietly become a favorite of many developers that find React overly complex and don't want to deal with the webpack tooling. With Vue you can simply include the Vue JavaScript file in the page, create a few templates, and you're on your way -- a throwback of the original JavaScript framework days.
尽管React.js在最新JavaScript框架浪潮中引起了很多关注,但Vue.js悄然成为许多开发人员的最爱,他们发现React过于复杂并且不想使用webpack工具。 使用Vue,您只需在页面中包含Vue JavaScript文件,创建一些模板,就可以了–与原始JavaScript框架时代相反。
Cloudinary, the awesome media storage and delivery service, provides APIs in just about every language to aid developers in using their service, including Node.js, Python, PHP, React, etc. I've been meaning to check out Vue and thought what better way to do so than creating media-centric components with the help of Cloudinary's API. My goal was to create a video component that mirrors what you see on many video-centric sites: load a thumbnail, play preview upon hover, and finally play the video when clicked. Let's go!
Cloudinary是很棒的媒体存储和交付服务,它几乎以每种语言提供API,以帮助开发人员使用他们的服务,包括Node.js,Python,PHP,React等。我一直在探究Vue并思考了什么比借助Cloudinary API创建以媒体为中心的组件更好的方法。 我的目标是创建一个视频组件,以反映您在许多以视频为中心的网站上看到的内容:加载缩略图,悬停时播放预览,最后在单击时播放视频。 我们走吧!
Quick note: the Vue.js component I'm creating for this post could be further optimized (use a single <video>
element, swap out controls, animated transitions, etc.) but I want to keep this post as simple and focused as possible. The main goal is to illustrate how Cloudinary and Vue.js are complimentary to each other and they're both incredibly easy to use!
快速说明:我为这篇文章创建的Vue.js组件可以进一步优化(使用单个<video>
元素,换出控件,动画过渡等),但是我想使这篇文章既简单又专注可能。 主要目的是说明Cloudinary和Vue.js如何相互补充,并且它们都非常易于使用!
Vue组件 (Vue Component)
I wanted to create a component because, much like React, they're easily contained and reusable. Let's start by taking a look at the component template.
我想创建一个组件是因为,就像React一样,它们很容易包含和重用。 让我们先看一下组件模板。
组件模板 (Component Template)
Seeing the HTML skeleton will provide insight into what we'll be manipulating:
看到HTML框架将提供对我们将要操作的内容的深入了解:
<div v-on:mouseenter="showPreview()" v-on:mouseleave="hidePreview()" class="cloudinary-video-item" :style="dimensions">
<div class="cloudinary-video-item-image">
<img :src="poster" :width="width" :height="height" alt="Video Preview">
</div>
<div class="cloudinary-video-item-active">
<video ref="previewVideo" autoplay loop :width="width" :height="height"></video>
</div>
<div class="cloudinary-video-item-video">
<video ref="fullVideo" autoplay controls :width="width" :height="height"></video>
</div>
<svg
v-on:click="play()"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="play-icon"
version="1.1"
height="50"
width="50"
viewBox="0 0 1200 1200">
<path
d="M 600,1200 C 268.65,1200 0,931.35 0,600 0,268.65 268.65,0 600,0 c 331.35,0 600,268.65 600,600 0,331.35 -268.65,600 -600,600 z M 450,300.45 450,899.55 900,600 450,300.45 z"
id="path16995" />
</svg>
</div>
Our component has four immediate child elements: three elements which show or display based on a CSS state, and a SVG "play" icon. The states are:
我们的组件具有四个直接子元素:三个基于CSS状态显示或显示的元素,以及SVG“播放”图标。 状态为:
(default) Show a thumbnail/poster image for the video
(默认)显示视频的缩略图/海报图像
(hover) Show a stitched, aggregated video preview (much like this post)
(悬停)显示缝合的汇总视频预览(非常类似于此帖子 )
- (active) Shows the entire video (有效)显示整个视频
state
attribute; their visibility will be manipulated by CSS selector matching each state.
state
属性的组件方法来操纵。 它们的可见性将通过与每个状态匹配CSS选择器进行操作。
组件属性 (Component Properties)
In the interest of keeping this component simple, I limit the number of properties to only those that are truly needed:
为了使该组件保持简单,我将属性的数量限制为仅真正需要的那些属性:
Vue.component('cloudinary-video', {
props: {
account: { type: String, required: true, default: 'david-wash-blog' },
alias: { type: String, required: true },
// These can be strings as they come in as attributes
width: { type: String, default: 400 },
height: { type: String, default: 300 }
},
Realize that Cloudinary's transformation API is so powerful that I could add dozens of properties to harness its every power, but this post would balloon into a novel! There are a few further properties which require computed values based on the simple properties, so let's also create those:
意识到Cloudinary的转换API是如此强大 ,以至于我可以添加数十个属性来利用其所有功能,但是这篇文章会膨胀成一本小说! 还有一些其他属性需要基于简单属性的计算值,因此我们还要创建这些属性:
computed: {
dimensions: function() {
return `width:${this.width}px; height:${this.height}px;`;
},
poster: function() {
return `http://res.cloudinary.com/${this.account}/video/upload/${this.alias}.jpg`;
},
preview: function() {
return `http://res.cloudinary.com/${this.account}/video/upload/so_0,du_2/l_video:${this.alias},fl_splice,so_12/du_2/fl_layer_apply/l_video:${this.alias},fl_splice,so_24/du_2/fl_layer_apply/l_video:${this.alias},fl_splice,so_36/du_2/fl_layer_apply/l_video:${this.alias},fl_splice,so_48/du_2/fl_layer_apply/l_video:${this.alias},fl_splice,so_80/du_2/fl_layer_apply/${this.alias}.mp4`;
},
fullVideo: function() {
return `http://res.cloudinary.com/${this.account}/video/upload/${this.alias}.mp4`;
}
},
Computed properties can reference simple properties, which I employ heavily in this component.
计算属性可以引用简单属性,我在此组件中大量使用了这些属性。
组成方法 (Component Methods)
Component methods will be employed to trigger functionality during our component's mouseenter
, mouseleave
, and click
events:
在组件的mouseenter
, mouseleave
和click
事件期间,将使用组件方法来触发功能:
methods: {
play: function () {
// Hide the preview
this.hidePreview();
// Set the state to "play" to show full video element
this.$el.setAttribute('state', 'playing');
// Set the full video element src
this.$refs.fullVideo.src = this.fullVideo;
},
showPreview: function() {
// If the full video is loaded and playing, ignore this event
if(this.$el.getAttribute('state') === 'playing') {
return;
}
// Update state for CSS / component's child element visibility
this.$el.setAttribute('state', 'preview');
// Set the preview video source
this.$refs.previewVideo.src = this.preview;
},
hidePreview: function() {
// If the full video is loaded and playing, ignore this event
if(this.$el.getAttribute('state') === 'playing') {
return;
}
// Update state for CSS / component's child element visibility
this.$el.setAttribute('state', '');
// Stop the video
this.$refs.previewVideo.pause();
}
},
While I do use the attribute state
, realize that I'm not using Flux or any other state management utility -- the attribute simply represents which of the three component states should be shown or hidden.
当我确实使用state
,请意识到我没有使用Flux或任何其他状态管理实用程序-该属性仅表示应显示或隐藏这三个组件状态中的哪一个。
组件CSS (Component CSS)
The CSS required for this component seems like a lot but it mostly manages the simple layout as well as "state": showing and hiding each component child element as required:
该组件所需CSS看起来很多,但它主要管理简单的布局以及“状态”:根据需要显示和隐藏每个组件子元素:
.cloudinary-video-item {
position: relative;
}
.cloudinary-video-item > div {
position: absolute;
top: 0;
left: 0;
}
.cloudinary-video-item img {
display: block;
}
.cloudinary-video-item svg {
position: absolute;
top: 40%;
left: 45%;
cursor: pointer;
opacity: 0.6;
}
.cloudinary-video-item svg:hover {
opacity: 0.9;
}
/* Default / image only state */
.cloudinary-video-item .cloudinary-video-item-active,
.cloudinary-video-item .cloudinary-video-item-video {
display: none;
}
/* Preview state */
.cloudinary-video-item[state=preview] .cloudinary-video-item-active {
display: block;
}
.cloudinary-video-item[state=preview] .cloudinary-video-item-image {
display: none;
}
/* Playing state */
.cloudinary-video-item[state=playing] .cloudinary-video-item-video {
display: block;
}
.cloudinary-video-item[state=playing] .cloudinary-video-item-image,
.cloudinary-video-item[state=playing] .cloudinary-video-item-active,
.cloudinary-video-item[state=playing] svg {
display: none;
}
There's a fair amount there but minified would hardly leave a footprint!
那里有很多,但缩小后几乎不会留下足迹!
使用组件 (Using the Component)
With each prop in props
containing a default value, except for the media alias of course, the component usage can be simple:
props
中的每个props
包含默认值,当然除了媒体别名之外,组件的用法也很简单:
<!-- simplest usage -->
<cloudinary-video alias="cartoon"></cloudinary-video>
<!-- customized usage -->
<cloudinary-video
account="david-wash-blog"
alias="cartoon"
width="640"
height="360">
</cloudinary-video>
And lastly adding a new Vue
call to kick everything off:
最后添加一个new Vue
调用以启动一切:
new Vue({ el: '#video-holder' })
That's how easy it is to create a Vue.js component for your Cloudinary media!
为您的Cloudinary媒体创建Vue.js组件非常容易!
闭幕 (Closing)
Creating a Vue component that uses multiple types of generated media from a single source was easy thanks to Cloudinary. Cloudinary generated the sample image, the video poster, the preview video, and quickly delivered those resources as well as the source video. Vue's simple API made creating the Cloudinary component fun and short on code. I look forward to playing around with Vue and Cloudinary to make some truly powerful media components!
创建使用多种类型生成的媒体的来自单个源的Vue的成分是容易由于Cloudinary 。 Cloudinary生成了示例图像,视频海报,预览视频,并快速交付了这些资源以及源视频。 Vue的简单API使创建Cloudinary组件变得有趣而又缺乏代码。 我期待与Vue和Cloudinary合作,制作一些真正强大的媒体组件!
vue创建组件和注册组件