前后端分离使得前端可以想开发后台一样开发,这种思想指导下的Vue是比较常用框架,这个框架的最大特色是页面组件化,为后面Vue组件单文件化提供基础;本主题的组件技术核心是两个部分:
1. 内置组件注册与实现;
2. 组件路由;
单文件组件会在webpack框架下使用Vue-Loader实现。
页面组件(Component)
-
页面设计是非常繁琐的事情,Web页面尽管提供了最基本的HTML标签(Tag:也称标记)来完成页面最基本的构成元素,但是提供更加高级的UI元素封装可以简化页面实现的复杂度。Vue提供了组件封装机制:
- 注册一个组件
- 使用Vue的全局函数component实现注册
- 在HTML中使用组件
- 像HTML标签一样使用组件
- 注册一个组件
-
Web页面模块化是开发者的需求,基本上所有Web框架都提供:
- Struts中Tag标签封装有页面模块化的框架;
- Spring框架中也有页面模块化封装;
- jQuery纯前端框架也提供模块化封装(通过样式分类封装实现);
Vue.component函数与全局组件
函数定义
Vue.component( id, [definition] )
- 参数说明:
-
id:字符串类型,用来指定组件名 -
[definition]:选项类型{},遵循Vue的选项格式。- 数据选项
- data/props/propsData/computed/methods/watch
- DOM选项
- el/template/render/renderError
- 声明周期钩子选项
- beforeCreate/created/beforeMount/mounted/beforeUpdate/updated
- activated/deactivated/beforeDestroy/destroyed/errorCaptured
- 资源选项
- directives/filters/compnents
- 组合选项
- parent/mixins/extends/provide/inject
- 其他选项
- name/delimiters/functional/model/inheritAttrs/comments
- 数据选项
-
使用例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 全局组件</title>
<script src="vue.min.js"></script>
</head>
<body>
<main id="main">
<!--3. 使用新注册的组件-->
<mydiv></mydiv>
</main>
<script type="text/javascript">
// 1.注册组件
Vue.component(
"mydiv",
{ // 选项格式:JSON对象格式
template: "<div style='width:200px; height:200px;background-color:red;'>定制组件</div>"
});
// 2. 创建Vue对象,该对象已经包含新注册的组件
var vm = new Vue(
{
el: "#main"
}
);
</script>
</body>
</html>
components选项与局部组件
- Vue对象的components选项用来定义(注册)局部组件;而且可以同时定义多个。语法格式与全局组件的定义一样。下面直接使用例子说明:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 局部组件</title>
<script src="vue.min.js"></script>
</head>
<body>
<main id="main">
<!--2. 使用注册的局部组件-->
<mydiv></mydiv>
<yourdiv></yourdiv>
</main>
<script type="text/javascript">
// 1. 注册局部组件(注册两个)
var vm = new Vue(
{
el: "#main",
components: {
"mydiv":{ // 选项格式:JSON对象格式
template: "<div style='width:200px; height:200px;background-color:red;'>定制局部组件一</div>"
},
"yourdiv":{ // 选项格式:JSON对象格式
template: "<div style='width:200px; height:200px;background-color:blue;'>定制局部组件二</div>"
},
}
}
);
</script>
</body>
</html>
props选项与组件的属性
props语法说明
Array<string> | Object
- 语法说明:
- props的类型可以是如下两种:
- 数组,用来指定属性列表
- JSON对象,用来指定高级配置选项;选项包含:
- type:可以是下列原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数、或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。
- default:为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。
- required:逻辑值true或者false,定义该 prop 是否是必填项。在非生产环境中,如果这个值为 truthy 且该 prop 没有被传入的,则一个控制台警告将会被抛出。
- validator:自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。
- props的类型可以是如下两种:
- 说明:
- 如果只有type选项,可以直接使用。
- 其中的required在html宽松的语法下,不一定有效果;
- 对类型的约束在Boolean职情况下也比较宽松。
数组的使用例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 组件数组属性</title>
<script src="vue.min.js"></script>
</head>
<body>
<main id="main">
<!--3. 使用新注册的组件-->
<!--注意:定制组件的属性也可以绑定数据-->
<mydiv p1="属性-1" p2="属性-2"></mydiv>
</main>
<script type="text/javascript">
// 1.注册组件
Vue.component(
"mydiv",
{ // 选项格式:JSON对象格式
template: "<div style='width:200px; height:200px;background-color:red;'>定制组件:{{p1}}-{{p2}}</div>",
props: ["p1","p2"]
});
// 2. 创建Vue对象,该对象已经包含新注册的组件
var vm = new Vue(
{
el: "#main"
}
);
</script>
</body>
</html>
对象的使用例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 组件对象属性</title>
<script src="vue.min.js"></script>
</head>
<body>
<main id="main">
<!--3. 使用新注册的组件-->
<!--注意:定制组件的属性也可以绑定数据-->
<mydiv p1="True" p2="AAA"></mydiv>
<mydiv p2="aaa"></mydiv>
</main>
<script type="text/javascript">
// 1.注册组件
Vue.component(
"mydiv",
{ // 选项格式:JSON对象格式
template: "<div style='width:200px; height:200px;background-color:red;'>定制组件:{{p1}}-{{p2}}</div>",
props: {
p1: [Boolean,String],
p2: {
type:Number,
default:30,
required:true,
validator:function (value){
console.log('hello');
return true;
}
}
}
});
// 2. 创建Vue对象,该对象已经包含新注册的组件
var vm = new Vue(
{
el: "#main"
}
);
</script>
</body>
</html>
组件的自定义事件
-
自定义事件使用
$emit指令触发事件 -
注意:
- 组件的自定义事件只能定制的注册组件能处理;其他组件无法接收(原生的标记组件无法接收);
$emit的定义
vm.$emit( eventName, […args] )
- 参数说明
- eventName:事件名
-
[…args]:传递给事件处理函数的参数;
例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 组件对象属性</title>
<script src="vue.min.js"></script>
</head>
<body>
<div id="main">
<mybutton v-on:myevent="myevent_handler"></mybutton>
<!--下面的事件无法接收-->
<!--
<div v-on:myevent="myevent_handler">被触发的按钮</div>
-->
</div>
<script type="text/javascript">
/*
组件的事件只能发送给自己,其他组件接收不到这个时间信号。
*/
Vue.component(
"mybutton",
{ // 选项格式:JSON对象格式
template: "<button v-on:click='click_handler'>点击</button>",
methods: {
click_handler: function(){
this.$emit("myevent"); // 抛出事件
},
}
}
);
var vm = new Vue(
{
el: "#main",
data:{
data1: "数据",
},
methods: {
myevent_handler: function(){ // 事件处理函数
alert("定制事件被触发!");
}
}
}
);
</script>
</body>
</html>
页面路由实现数据区导航
-
Vue的路由需要单独的库,下载地址:
https://unpkg.com/vue-router/dist/vue-router.js
-
页面路由主要管理页面链接导航,以及导航的会话历史数据与跟踪;如果仅仅是超链接,则使用比较简单。
-
注意:
- 页面路由会添加
#实现是内部锚点导航;
- 页面路由会添加
使用路由实现链接
-
使用vue-router的
<router-link>定制标记即可;使用方式两个部分:- 使用
router-link标记导航; - 挂载
router-link到Vue环境;
- 使用
-
理由使用例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-Router</title>
<script src="vue.min.js"></script>
<script src="vue-router.js"></script>
</head>
<body>
<div id="main">
<!--1. 使用router实现导航菜单-->
<router-link to="/url1">到组件1</router-link>
<router-link to="/url2">到组件2</router-link>
<!--2. 导航组件显示区:渲染的位置-->
<br>
<router-view></router-view>
</div>
<script>
const target1 = {template:"<button>链接1</button"};
const target2 = {template:"<input type='text' value='请输入'/>"};
// 3. 定义router对象
const router = new VueRouter({
// mode: "history", // 默认使用#实现锚点导航hash,history使用相对url导航(站点资源)。
routes: [
{path: '/url1', component: target1},
{path: '/url2', component: target2},
],
});
// 4. 挂载router对象
var vm = new Vue({
router
}
).$mount('#main');
</script>
</body>
</html>
- 说明:
- 导航还有很多内容,包括querystring等处理,链接嵌套等,这里暂时不介绍,仅仅了解router提供的设计模式的优点。
使用html文件作为路由组件
- 可以在router-link中直接使用外部html文件,但是需要设置下router的model。下面是例子:
- hash与hostory不能混用。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-Router</title>
<script src="vue.min.js"></script>
<script src="vue-router.js"></script>
<link rel="shortcut icon" href="#" />
</head>
<body>
<div id="main">
<!--1. 使用router实现导航菜单-->
<router-link to="./v01_vue_data.html">到组件1</router-link>
<!--2. 导航组件显示区:渲染的位置-->
<br>
<router-view></router-view>
</div>
<script>
const target2 = {template:"<input type='text' value='请输入'/>"};
// 3. 定义router对象
const router = new VueRouter({
mode: "history", // 默认使用#实现锚点hash导航,history使用相对url导航(站点资源)。
});
// 4. 挂载router对象
var vm = new Vue({
router
}
).$mount('#main');
</script>
</body>
</html>
多视图路由
- 可以一个路由url使用的是default组件,一个路由url可以绑定多个组件,每个组件指定名字,改名字可以对应显示在不同的视图中,下面是使用例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-Router</title>
<script src="vue.min.js"></script>
<script src="vue-router.js"></script>
<link rel="shortcut icon" href="#" />
</head>
<body>
<div id="main">
<!--视图激活方式:(一)-->
<!-- <router-link to="/url1">链接</router-link> -->
<router-view></router-view>
<router-view name="v1"></router-view>
<router-view name="v2"></router-view>
</div>
<script>
const target1 = {template:"<button>链接1</button"};
const target2 = {template:"<input type='text' value='请输入'/>"};
const target3 = {template:"<hr>"};
// 3. 定义router对象
const router = new VueRouter({
mode: "hash",
routes: [
{
path: '/url1',
components: {
default: target1,
v1: target2,
v2:target3
}
},
],
});
// 4. 挂载router对象
var vm = new Vue({
router
}
).$mount('#main');
// 激活方式:(二)
router.push("url1");
</script>
</body>
</html>
说明
- vue与vue-router只是解决了页面模块化问题,实际上并没有提供vue文件作为组件的功能与机制;
- 把vue文件作为组件的解决方案是vue-loader,他会对vue文件进行解析处理(主要处理html,css与javascript三个部分),vue-loader使用的是javascript服务器脚本ES6以上版本,这个需要专门的javascript运行环境,node.js就是Javascript的运行环境(号称Javascript虚拟机,与JVM同等地位)
- 使用浏览器javascript自己组织多个页面太痛苦了(python等服务器脚本语言目前还有ES6这种彪悍的对多个页面组织的封装框架),我们引入基于ES6的Web前端框架来解决多个页面组织的问题,那我们就需要了解下node.js,然后了解Webpack这个把多个文件组织其他提供给浏览器处理的框架技术:
- Webpack使用的就是vue-loader等来组织各种web资源的。











网友评论