本文参考了跬步者的文章,请戳这里,真的写得太详细了,在这里只是直接总结,方便自己记忆
ps:本博客的代码均是可以直接拷贝运行的,希望能对大家有帮助
1.component的创建,注册,使用
a.Vue.extend({...})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue.extend</title>
<script src="http://lib.baomitu.com/vue/2.3.4/vue.js"></script>
</head>
<body>
<div id="app">
<p>我是全局注册</p>
<qj-example></qj-example>
<p>我是局部注册的</p>
<jb-example></jb-example>
</div>
<script>
//使用组件构造器构造一个组件
var example = Vue.extend({
template: "<h1>我是使用Vue.extend这个组件构造器所构造的组件</h1>"
});
//将构造好的组件注册在需要用这个组件的实例上
//你可以进行全局注册:Vue.component(组件的名称,{组件的选项对象}就是使用组件构造器所返回的对象)
Vue.component('qj-example', example);
var vue = new Vue({
el: '#app',
//你也可以进行局部注册,此时components可是复数哦!
components: {
'jb-example': example
}
});
</script>
</body>
</html>
b.每次创建都要使用一遍Vue.extend({...}),这样过于繁琐,我们可以使用Vue.extend({...})的语法糖,这种方式就是我们在各个教程上看到的最普遍的方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue.extend</title>
<script src="http://lib.baomitu.com/vue/2.3.4/vue.js"></script>
</head>
<body>
<div id="app">
<p>我是全局注册</p>
<qj-example></qj-example>
<p>我是局部注册的</p>
<jb-example></jb-example>
</div>
<script>
//使用组件构造器构造一个组件
// var example = Vue.extend({
// template: "<h1>我是使用Vue.extend这个组件构造器所构造的组件</h1>"
// });
//将构造好的组件注册在需要用这个组件的实例上
//你可以进行全局注册
//这样写,vue会自动帮你调用'组件构造器'的
Vue.component('qj-example', {
template: "<h1>我是使用Vue.extend的语法糖所构造的组件</h1>"
});
var vue = new Vue({
el: '#app',
//你也可以进行局部注册,此时components可是复数哦!
components: {
'jb-example': {
template: "<h2>我是使用Vue.extend的语法糖所构造的组件</h2>"
}
}
});
</script>
</body>
</html>
2.template的一些问题
如果模板非常庞大,岂不是要写的很麻烦,也不容易维护,比如如果你把上面template的参数换成下面这一段,那你维护起来岂不是要哭,so...(下方代码请注意颜色的标注)
'<p>本文参考了<a href="">跬步者</a>的文章,请戳<a href="" target="_blank">这里</a>,真的写得太详细了,在这里只是直接总结,方便自己记忆</p>
<p>ps:本博客的代码均是可以直接拷贝运行的,希望能对大家有帮助</p>'
a.使用script标签来注册一个模板 这里要注意script标签的type类型要使用'text/x-template',不知道大家使用过那个小小的juicer.js没有,他就是使用了type属性。
ps1:script不写type默认是text/javascript,如果写了不被识别的type将被浏览器忽略。 script的type为各种template的时候,可能就是使用了模板引擎。
ps2.请记住,Component template should contain exactly one root element.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue.extend</title>
<script src="http://lib.baomitu.com/vue/2.3.4/vue.js"></script>
</head>
<body>
<div id="app">
<p>我是全局注册</p>
<qj-example></qj-example>
<p>我是局部注册的</p>
<jb-example></jb-example>
</div>
<!-- 我是使用script标签定义的模板 用编辑器分分钟整理好结构-->
<script type="text/x-template" id="my-component">
<div>//如果你不给定一个根元素,会报错哦,在这里就是你吧这对div标签删掉
<p>本文参考了
<a href="">跬步者</a>的文章, 请戳
<a href="" target="_blank">这里</a>, 真的写得太详细了,在这里只是直接总结,方便自己记忆
</p>
<p>ps:本博客的代码均是可以直接拷贝运行的,希望能对大家有帮助</p>
</div>
</script>
<script>
Vue.component('qj-example', {
template: '#my-component'
});
var vue = new Vue({
el: '#app',
//你也可以进行局部注册,此时components可是复数哦!
components: {
'jb-example': {
template: '#my-component'
}
}
});
</script>
</body>
</html>
b.vue支持对html5的<template>标签做处理,对这个标签不熟悉的话,可以戳这里
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue.extend</title>
<script src="http://lib.baomitu.com/vue/2.3.4/vue.js"></script>
</head>
<body>
<div id="app">
<p>我是全局注册</p>
<qj-example></qj-example>
<p>我是局部注册的</p>
<jb-example></jb-example>
</div>
<!-- 我是使用template标签定义的模板 用编辑器分分钟整理好结构-->
<template id="my-component">
<div>
<p>本文参考了
<a href="">跬步者</a>的文章, 请戳
<a href="" target="_blank">这里</a>, 真的写得太详细了,在这里只是直接总结,方便自己记忆
</p>
<p>ps:本博客的代码均是可以直接拷贝运行的,希望能对大家有帮助</p>
</div>
</template>
<script>
Vue.component('qj-example', {
template: '#my-component'
});
var vue = new Vue({
el: '#app',
//你也可以进行局部注册,此时components可是复数哦!
components: {
'jb-example': {
template: '#my-component'
}
}
});
</script>
</body>
</html>
2.组件的data选项,想看所有选项的话,请戳这里
我就自己不瞎说了,直接贴个文档,如果不明白可以留言,我会尽力解释的
3.父组件向子组件传递数据
这里我改写了跬步者的例子,基本是一样的。
<!-- component -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue.extend</title>
<script src="http://lib.baomitu.com/vue/2.3.4/vue.js"></script>
<link href="http://lib.baomitu.com/twitter-bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<style>
#app {
padding: 10% 30%;
}
</style>
</head>
<body>
<div id="app">
<input type="text" v-model="searchWord" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
<my-table :title="tableName" :list="tableList" :search-key="searchWord"></my-table>
</div>
<template id="my-grid">
<table class="table">
<thead>
<tr>
<th scope="col" v-for="item in title">{{item}}</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in grid">
<th scope="row">{{index+1}}</th>
<td>{{grid[index].name}}</td>
<td>{{grid[index].sex}}</td>
<td>{{grid[index].age}}</td>
</tr>
</tbody>
</table>
</template>
<script>
var vue = new Vue({
el: '#app',
data: {
searchWord: '',
tableName: ['#', 'name', 'sex', 'age'],
tableList: [{
name: 'li',
sex: 'boy',
age: '10'
}, {
name: 'zhang',
sex: 'gril',
age: '20'
}, {
name: 'yang',
sex: 'boy',
age: '40'
}, ]
},
components: {
'my-table': {
template: '#my-grid',
props: {
title: Array,
list: Array,
searchKey: String
},
data() {
return {
grid: this.list, //子组件接收一个父组件数据的副本
}
},
watch: {
searchKey: function(val) {
console.log(val);
if (val != '') {
this.grid = this.list.filter(function(item, index, arr) {
for (let elem of Object.values(item)) {
if (elem.includes(val)) {
return item;
}
}
}, this);
} else {
this.grid = this.list;
}
this.$forceUpdate();
}
}
}
}
});
</script>
</body>
</html>
3.子组件向父组件传递数据(这个我回头写好例子了再补上)
在之前的例子上加以改动,添加需求,让组件以数组形式返回符合条件的姓名,让父组件显示,在之前代码基础上添加橙色色代码即可即可
<!-- component -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue.extend</title>
<script src="http://lib.baomitu.com/vue/2.3.4/vue.js"></script>
<link href="http://lib.baomitu.com/twitter-bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<style>
#app {
padding: 10% 30%;
}
</style>
</head>
<body>
<div id="app">
<input type="text" v-model="searchWord" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
<my-table :title="tableName" :list="tableList" :search-key="searchWord" @searchresult="showSearch"></my-table>在使用子组件时用v-on/@注册searchresult这个自定义事件,父组件用showSearch这个函数接收自定义事件返回的参数
<div>
<p>符合条件的学生姓名:{{showName.join(",")}}</p>
</div>
</div>
<template id="my-grid">
<table class="table">
<thead>
<tr>
<th scope="col" v-for="item in title">{{item}}</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in grid">
<th scope="row">{{index+1}}</th>
<td>{{grid[index].name}}</td>
<td>{{grid[index].sex}}</td>
<td>{{grid[index].age}}</td>
</tr>
</tbody>
</table>
</template>
<script>
var vue = new Vue({
el: '#app',
data: {
searchWord: '',
tableName: ['#', 'name', 'sex', 'age'],
tableList: [{
name: 'li',
sex: 'boy',
age: '10'
}, {
name: 'zhang',
sex: 'gril',
age: '20'
}, {
name: 'yang',
sex: 'boy',
age: '40'
}],
showName: [],
},
methods: {
showSearch(val) {
this.showName = val;这个val就是result
},
},
components: {
'my-table': {
template: '#my-grid',
props: {
title: Array,
list: Array,
searchKey: String
},
data() {
return {
grid: this.list, //子组件接收一个父组件数据的副本
}
},
watch: {
searchKey: function(val) {
console.log(val);
let result = [];
if (val != '') {
this.grid = this.list.filter(function(item, index, arr) {
for (let elem of Object.values(item)) {
if (elem.includes(val)) {
result.push(arr[index].name);
return item;
}
}
}, this);
} else {
this.grid = this.list;
}
this.$forceUpdate();
this.$emit('searchresult', result);使用vue的实例方法$emit发送自定义事件,饼返回result这个参数
}
}
}
}
});
</script>
</body>
</html>
连雨不知春去,一晴方觉夏深