目录
一、Vue.js 组件
组件是什么
如效果所示,每个产品展示,就是一个模板。 只用做一个模板,然后照着这个模板,传递不同的参数就可以看到不同的产品展示了。
这个模板,就是组件。
当前看到的这个效果比较复杂,接下来会由浅入深,慢慢地把这个效果做出来。
注: 点击产品,还可以增加销售数量。 虽然业务上不会真的增加销售数量,但是这里是演示组件也有自定义事件的效果。
局部组件
接下来就由浅入深地展开组件的学习。 先看最简单的局部组件。
在 Vue对象里增加 components:
components:{
'product':{
template:'<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>'
}
然后在视图里,通过如下方式就可以调用了
<product></product>
如果想重复使用,则多写几次就行了
<product></product>
<product></product>
<product></product>
<div id="div1">
<product></product>
<product></product>
<product></product>
</div>
<script>
new Vue({
el: '#div1',
components:{
'product':{
template:'<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>'
}
}
})
</script>
<style>
div.product{
float:left;
border:1px solid lightGray;
width:200px;
margin:10px;
cursor: pointer;
}
</style>
全局组件
和vue.js 里的过滤器一样,有的组件会在不同页面使用,这个时候就可以考虑用全局组件。
Vue.component('product', {
template: '<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>'
})
写法其实跟局部差不多,只是提出来了。 这样到处都可以用了。
<div id="div1">
<product></product>
<product></product>
<product></product>
</div>
<script>
Vue.component('product', {
template: '<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>'
})
new Vue({
el: '#div1'
})
</script>
<style>
div.product{
float:left;
border:1px solid lightGray;
width:200px;
margin:10px;
cursor: pointer;
}
</style>
参数
像前面的例子,产品名称都是固定的,这样肯定不行,所以就要能够传递参数给组件。
设置参数name, 并且在组件里使用这个name:
Vue.component('product', {
props:['name'],
template: '<div class="product" >{{name}}</div>'
})
调用的时候,就当作是一个自定义属性传进去就可以了
<product name="MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮"></product>
<product name="宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包"></product>
<product name="唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮"></product>
<div id="div1">
<product name="MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮"></product>
<product name="宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包"></product>
<product name="唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮"></product>
</div>
<script>
Vue.component('product', {
props:['name'],
template: '<div class="product" >{{name}}</div>'
})
new Vue({
el: '#div1'
})
</script>
<style>
div.product{
float:left;
border:1px solid lightGray;
width:200px;
margin:10px;
cursor: pointer;
}
</style>
动态参数
所谓的动态参数,就是指组件内的参数可以和组件外的值关联起来
如效果所示,在组件外的input输入数据,就可以传递到组件内了
关键是这一行,name表示组件内的属性name, outName就是组件外的
<product v-bind:name="outName"></product>
<div id="div1">
组件外的值:<input v-model="outName" ><br>
<product v-bind:name="outName"></product>
</div>
<script>
Vue.component('product', {
props:['name'],
template: '<div class="product" >{{name}}</div>'
})
new Vue({
el: '#div1',
data:{
outName:'产品名称'
}
})
</script>
<style>
div.product{
float:left;
border:1px solid lightGray;
width:200px;
margin:10px;
cursor: pointer;
}
</style>
自定义事件
增加自定义事件和在一个Vue对象上增加 methods 是一样的做法
先来个methods:
methods:{
increaseSale:function(){
this.sale++
}
}
然后在组件里:
v-on:click="increaseSale"
<div id="div1">
<product name="MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮" sale="10" ></product>
<product name="宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包" sale="20" ></product>
<product name="唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮" sale="30" ></product>
</div>
<script>
Vue.component('product', {
props:['name','sale'],
template: '<div class="product" v-on:click="increaseSale">{{name}} 销量: {{sale}} </div>',
methods:{
increaseSale:function(){
this.sale++
}
}
})
new Vue({
el: '#div1'
})
</script>
<style>
div.product{
float:left;
border:1px solid lightGray;
width:200px;
margin:10px;
cursor: pointer;
}
</style>
注,这里是在组件上增加的,而不是在视图上增加的。
测试: 点击产品,就会增销量
遍历 json 数组
大部分时候是拿到一个 json 数组,然后遍历这个 json 数组为多个组件实例。
-
首先准备产品数组
products:[ {"name":"MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮","sale":"18"}, {"name":"宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包","sale":"35"}, {"name":"唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮","sale":"29"} ]
-
然后在视图里通过 v-for 遍历 products
<product v-for="item in products" v-bind:product="item"></product>
-
接着修改组件,让接受的参数为 v-bind:product 里的这个 product,显示和方法里也通过 product.xxx 来调用。
Vue.component('product', {
props:['product'],
template: '<div class="product" v-on:click="increaseSale">{{product.name}} 销量: {{product.sale}} </div>',
methods:{
increaseSale:function(){
this.product.sale++
}
}
})
<div id="div1">
<product v-for="item in products" v-bind:product="item"></product>
</div>
<script>
Vue.component('product', {
props:['product'],
template: '<div class="product" v-on:click="increaseSale">{{product.name}} 销量: {{product.sale}} </div>',
methods:{
increaseSale:function(){
this.product.sale++
}
}
})
new Vue({
el: '#div1',
data:{
products:[
{"name":"MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮","sale":"18"},
{"name":"宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包","sale":"35"},
{"name":"唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮","sale":"29"}
]
}
})
</script>
<style>
div.product{
float:left;
border:1px solid lightGray;
width:200px;
margin:10px;
cursor: pointer;
}
</style>
最开始效果步骤里的代码
最开始效果步骤里的代码其实就是在前面的基础上,增加了一些样式,增加了一些字段而已。
另外 template 部分因为比较复杂,就不好写在一个 单引号 ’ ’ 里维护起来,所以就直接写在html里,然后通过html dom 获取出来,这样编写起来略微容易一点。
var tempalateDiv=document.getElementById("tempalate").innerHTML;
其他的就没有什么新东西啦
<div id="tempalate" style="display:none">
<div class="product" v-on:click="increaseSales">
<div class="price">
¥ {{product.price}}
</div>
<div class="productName">
{{product.name}}
</div>
<div class="sale"> 月成交 {{product.sale}} 笔</div>
<div class="review"> 评价 {{product.review}} </div>
</div>
</div>
<div id="div1">
<product v-for="item in products" v-bind:product="item"></product>
</div>
<script>
var tempalateDiv=document.getElementById("tempalate").innerHTML;
var templateObject = {
props: ['product'],
template: tempalateDiv,
methods: {
increaseSales: function () {
this.product.sale = parseInt(this.product.sale);
this.product.sale += 1
this.$emit('increment')
}
}
}
Vue.component('product', templateObject)
new Vue({
el: '#div1',
data:{
products:[
{"name":"MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮","price":"889","sale":"18","review":"5"},
{"name":"宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包","price":"322","sale":"35","review":"12"},
{"name":"唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮","price":"523","sale":"29","review":"3"},
]
}
})
</script>
<style>
div.product{
float:left;
border:1px solid lightGray;
width:200px;
margin:10px;
cursor: pointer;
}
div.product:hover{
border:1px solid #c40000;
}
div.price{
color:#c40000;
font-weight:bold;
font-size:1.2em;
margin:10px;
}
div.productName{
color:gray;
font-size:0.8em;
margin:10px;
}
div.sale{
float:left;
width:100px;
border:1px solid lightgray;
border-width:1px 0px 0px 0px;
color:gray;
font-size:0.8em;
padding-left:10px;
}
div.review{
overflow:hidden;
border:1px solid lightgray;
border-width:1px 0px 0px 1px;
color:gray;
font-size:0.8em;
padding-left:10px;
}
</style>
二、Vue.js 自定义指令
简单例子
像 v-if, v-bind, v-on 等等前面学习的指令,都是 vus.js 自带的指令,那么除了这些指令,开发者还可以开发自定义的指令,比如 v-xart 来做一些效果。
如效果所示, 一旦使用了 v-xart 这个指令,那么文字颜色就会变成粉红,后面也会自动加上 (x-art)
自定义指令的方式:
-
使用Vue.directive 来自定义
-
第一个参数就是 指令名称 xart
-
el 表示当前的html dom对象
-
在方法体内就可以通过 innerHTML style.color 等方式操控当前元素了
Vue.directive('xart', function (el) { el.innerHTML = el.innerHTML + ' ( x-art ) ' el.style.color = 'pink' })
<div id="div1">
<div v-xart> 好好学习,天天向上 </div>
</div>
<script>
Vue.directive('xart', function (el) {
el.innerHTML = el.innerHTML + ' ( x-art ) '
el.style.color = 'pink'
})
new Vue({
el: '#div1'
})
</script>
带参数的自定义指令
上面例子是不带参数的,现在带上参数
binding.value 就是指 v-xart=“xxx” 这个xxx。 此时xxx是一个json对象,所以就可以通过.text, .color取出对应的值出来。
Vue.directive('xart', function (el,binding) {
el.innerHTML = el.innerHTML + '( ' + binding.value.text + ' )'
el.style.color = binding.value.color
})
视图上用就传递个json 对象进去
<div v-xart="{color:'red',text:'best learning video'}"> 好好学习,天天向上 </div>
当然也可以传递个简单的
<div v-xart="blue"> 好好学习,天天向上 </div>
那么在函数里就直接调用 binding.value 就好了
<div id="div1">
<div v-xart="{color:'red',text:'best learning video'}"> 好好学习,天天向上 </div>
</div>
<script>
Vue.directive('xart', function (el,binding) {
el.innerHTML = el.innerHTML + '( ' + binding.value.text + ' )'
el.style.color = binding.value.color
})
new Vue({
el: '#div1'
})
</script>
钩子函数
钩子函数是什么意思? 又叫做回调函数,或者事件响应函数。 指的是,一个指令在创建过程中,经历不同生命周期的时候,vue.js 框架调用的函数。
事件常见的有如下几种:
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
unbind:只调用一次,指令与元素解绑时调用。
以bind为例,可以传递主要是用到binding里的属性
name:指令名,不包括 v- 前缀。
value:指令的绑定值,本例就是hello vue.js
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。本例就是 message
arg:传给指令的参数,本例就是hello
modifiers:一个包含修饰符的对象。本例就是 .a .b
这样拿到这些自定义指令的各项参数,那么在函数体里就方便做各种自定义功能了
vnode是虚拟节点,里面具体什么意思,我也不太懂。。。好像也用不到,pass 吧~
<div id="div1">
<div v-xart:hello.a.b="message"> </div>
</div>
<script>
Vue.directive('xart', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
},
update: function (newValue, oldValue) {
// 值更新时的工作
// 也会以初始值为参数调用一次
},
unbind: function () {
// 清理工作
// 例如,删除 bind() 添加的事件监听器
}
})
new Vue({
el: '#div1',
data:{
message:'hello vue.js'
}
})
</script>
三、Vue.js 路由
vue.js 里的路由概念
vue.js 里的路由相当于就是局部刷新。
如效果所示,点击左边的菜单,右边的内容在不刷新整个页面的情况下,进行局部刷新
vue-router.min.js
为了实现路由,需要一个额外的库: vue-router.min.js
<script src="http://how2j.cn/study/vue-router.min.js"></script>
路由代码讲解
代码的讲解都写在注释里了,挨个看过去就好了
<script src="https://how2j.cn/study/vue.min.js"></script>
<script src="https://how2j.cn/study/vue-router.min.js"></script>
<head>
<style>
a{
text-decoration: none;
}
a.router-link-active{
/* color:blue; */
background-color: lightGray;
}
div.menu{
border:1px solid gray;
float:left;
}
div.menu a{
display:block;
}
div.workingRoom{
margin-left:100px;
}
div#app{
width:500px;
padding:10px;
margin:10px auto;
}
</style>
</head>
<div id="app">
<div class="menu">
<!--
router-link 相当于就是超链
to 相当于就是 href
-->
<router-link to="/user">用户管理</router-link>
<router-link to="/product">产品管理</router-link>
<router-link to="/order">订单管理</router-link>
</div>
<div class="workingRoom">
<!--
点击上面的/user,那么/user 对应的内容就会显示在router-view 这里
-->
<router-view></router-view>
</div>
</div>
<script>
/*
* 申明三个模板( html 片段 )
*/
var user = { template: '<p>用户管理页面的内容</p>' };
var second = { template: '<p>产品管理页面的内容</p>' };
var order = { template: '<p>订单管理页面的内容</p>' };
/*
* 定义路由
*/
var routes = [
{ path: '/', redirect: '/user'}, // 这个表示会默认渲染 /user,没有这个就是空白
{ path: '/user', component: user },
{ path: '/product', component: second },
{ path: '/order', component: order }
];
/*
* 创建VueRouter实例
*/
var router = new VueRouter({
routes:routes
});
/*
* 给vue对象绑定路由
*/
new Vue({
el:"#app",
router
})
</script>