Vue学习笔记-组件
Vue之组件
vue的核心就是组件的使用,玩好了组件才能将前面的基础更好的运用起来。
组件使我们的项目解耦,更加符合vue的设计思想MVVM。
组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:

例如,你可能会有页头,侧边栏,内容区等组件,每个组件又包含了其它的像导航栏链接、博文之类的组件
组件的创建
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>组件</title>
</head>
<body>
<div id="app"></div>
<script src="vue.js"></script>
<script>
// Vheader是组件名,最好大写开头
Vue.component('Vheader', {
// 和实例对象不一样,这里data不再返回对象,必须要是个函数,而且必须return
data: function () {
return {
// 必须要return,哪怕是空对象
}
},
template: `<div class="header">
<div class="w">
<div class="w1">
<img src="./logo.png">
</div>
<div class="w-r">
<button>登陆</button><button>注册</button>
</div>
</div>
</div>`
});
var app = new Vue({
el: '#app',
data: {},
computed: {},
methods: {}
})
</script>
</body>
</html>
组件的使用
组件是可服用的Vue实例,并且带有一个名字,这个例子中是<Vheader> 。
我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
<div id="app">
<Vheader></Vheader>
</div>
组件的复用
<div id="app">
<Vheader></Vheader>
<Vheader></Vheader>
<Vheader></Vheader>
</div>
vue-cli脚手架安装和webpack-simple模板项目生成
vue-cli是一个官方发布vue.js项目脚手架,使用vue-cli可以快速创建vue项目
安装nodejs
官网下载安装
node -v检查是否安装成功
npm 是 nodejs package manager ,跟python的pip java mvn一样
安装vue-cli
安装好node之后,我们就可以直接全局安装vue-cli:
npm install -g vue-cli
安装慢的话用淘宝镜像,百度淘宝镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org
如果安装失败使用npm cache clean清理缓存,然后再重新安装。
安装完成后vue -V查看vue版本。
vue hlep查看可用命令
vue list查看官方提供的模板

安装webpack-simple模板
初始化项目,加项目名myProject就创建一个项目名的目录里生成,不加名字默认再当前目录生成项目
vue init webpack-simple myProject

最后一步选N,sass是vue的预处理语言还不会。
然后它就告诉你要继续干什么:

webpack + nodejs 使我们更方便的开发,热重载
使用的webpack模板
打开项目myProject,映入眼帘的是一个也看不懂。。
等等..main.js:
import Vue from 'vue' import App from './App.vue' new Vue({ el: '#app', render: h => h(App) })
可以看出,这个和django的manage.py文件一样都是一个入口文件。
入口文件引的第一个文件就是App.vue:
看看人家是怎么设计的:
<!--一个组件有三部分组成-->
<!-- 一个页面就把三个部分全部包含了 -->
<template>
<!--第一部分,页面的结构-->
<!-- 注意template下整个必须是一个闭合标签,因为他是一个大组件包裹一个个小组件 -->
<!-- 比如把下面的注释去掉就会报错 -->
<!-- <div class="app2"></div> -->
<div class="app">
<h3>{{ msg }}</h3>
<p>heihei</p>
</div>
</template>
<script>
// 第二部分,页面的业务逻辑
export default {
name:'App', // 只是个名字
data(){ // 数据属性必须是个函数
return {
msg:'组件'
}
},
methods: {
},
computed: {
}
}
</script>
<style>
/*第三部分,css样式*/
</style>
解耦组件
上面的是一个大组件,要解耦成一个个小组件,所以我们要创建一个存放一个个小组件的文件加。
src下面新建一个folder,就叫components。
并新建三个文件:

每个文件里的结构,跟App.vue里的一样。
<template>
<header class="nav"> <!--footer的class:foot,content:wrap-->
我是header
</header>
</template>
<script>
export default {
name:'Vheader',// footer:Vfooter,content:content
data(){
return {
}
},
}
</script>
<style scoped> //scoped:组件里的样式只在自己的组件里生效
</style>
引入子组件
接下来这些小组件怎么在大组件里用呢:
<template>
<div class="app">
<h3>{{ msg }}</h3>
<p>heihei</p>
<Vcontent></Vcontent>
<Vcontent></Vcontent>
<Vcontent></Vcontent>
</div>
</template>
<script>
// 1. 先引入子组件
import Vcontent from './components/Vcontent.vue'
import Vheader from './components/Vheader.vue'
import Vfooter from './components/Vfooter.vue'
export default {
name:'App',
data(){
return {
msg:'组件'
}
},
methods: {
},
computed: {
},
// 2. 挂载组件
components:{
Vheader, // 相当于Vheader:Vheader,key和value相同可以简写
Vcontent,
Vfooter,
}
}
</script>
<style>
</style>
组件间传值
父组件向子组件传递数据,通过Prop
1. 父组件向子组件传值第一步就是, 绑定自定义的属性,在导入的子组件标签: <Vheader :title = '父组件中data声明的数据属性'/> 2. 父子传值的第二步就是,要通过props验证,再子组件里写这个方法 // 数组类型就必须写Array,写Str就会报错,对应类型可以查官网,然后就可以在子组件里用这个数据量了 props:{ cityArray:Array, } type 可以是下列原生构造函数中的一个: String Number Boolean Array Object Date Function Symbol
子组件传递数据到父组件,通过自定义事件
1. 子父组件传值,第一步就是自定义事件 <Vcontent v-on:addCunHandler = 'addHandler'></Vcontent> 2. 给子组件中的某个按钮绑定原生事件,我们可以调用内建的 this.$emit('自定义的事件名','传递的数据'),来向父级组件触发一个自定义的事件. methods:{ addCunHandler(){ // 通过$emit触发自定义事件 // 参数1:自定义事件的名字 // 参数2:数据 this.$emit('addCunHandler','北海北'); } },
MarkDown项目
写一个markdown项目,练习一下组件传值
父组件:App.vue
<template>
<div class="app">
<Vheader></Vheader>
<h2>{{ currentMsg }}</h2>
<!-- webpack里的file-loader工具能把图片看做变量 -->
<!-- 所以取图片用下面这种方式即可 -->
<img :src="imgSrc">
<ul>
<li v-for = 'item in getArray'>
<!-- a标签里的href="javascript;"表示阻止a标签的事件,等于a标签失效了 -->
<a href="javascript;">{{item}}</a>
</li>
</ul>
<!-- 来个点击事件 -->
<button @click='clickHandler'>修改</button>
<!-- 子父组件传值,第一步就是自定义事件 -->
<Vcontent v-on:addCunHandler = 'addHandler'></Vcontent>
<!-- 父子组件传值,第一步就是绑定自定义属性 -->
<Vfooter :cityArray = 'citys'></Vfooter>
</div>
</template>
<script>
import imgSrc from './assets/logo.png'
// 子组件渲染到父组件的第一步就是,导入
import Vheader from './components/Vheader.vue'
import Vcontent from './components/Vcontent.vue'
import Vfooter from './components/Vfooter.vue'
export default {
name:'App',
data(){
return {
msg:'hello world',
stars:[
"nsn","alex",'nezha'
],
imgSrc:imgSrc,
citys:['沙河','通州','西二旗']
}
},
methods: {
clickHandler(){
this.msg = '哈哈哈',
this.stars.push('anglebaby')
},
addHandler(str){
this.citys.push(str)
}
},
// 所有的属性,都可以被计算属性绑定起来,多用计算属性
computed: {
currentMsg(){
return this.msg;
},
getArray(){
return this.stars
}
},
// 子组件渲染到父组件的第二步就是,挂载
components:{
Vheader,
Vfooter,
Vcontent
}
}
</script>
<style>
*{
padding: 0px;
margin: 0px;
}
</style>
子组件Vfooter
<template>
<footer class="foot">
<ul v-for = 'item in cityArray'>
<li>{{item}}</li>
</ul>
</footer>
</template>
<script>
export default {
name:'Vfooter',
data(){
return {
}
},
// 父子传值的第二步就是,一定要通过props验证
// 数组类型就必须写Array,写Str就会报错,对应类型可以查官网,然后就可以在上面用了
props:{
cityArray:Array,
}
}
</script>
<style>
</style>
子组件Vcontent
<template>
<div class="wrap">
<div class="t">
<button @click='addCunHandler'>添加一个村庄</button>
</div>
<div class="mark">
<textarea rows="10" cols="100" class="editor" v-model = 'markValue'></textarea>
<div class="show" v-html = 'markedValue'></div>
</div>
</div>
</template>
<script>
// npm install marked --save,别人写好的markdown工具,直接解析你的markdown语法
import Marked from 'marked'
export default {
name:'Vcontent',
data(){
return {
markValue:''
}
},
methods:{
// 子组件向父组件传值,第二步就是触发自定义事件
addCunHandler(){
// 通过$emit触发自定义事件
// 参数1:自定义事件的名字
// 参数2:数据
this.$emit('addCunHandler','北海北');
}
},
computed:{
markedValue(){
return Marked(this.markValue)
}
}
}
</script>
<style scoped>
.t {
width: 300px;
height: 100px;
}
.mark{
width:1210px;
height: 600px;
margin: 0 auto;
}
.editor,.show{
float: left;
width: 603px;
height: 600px;
border: 1px solid #666;
}
</style>
子组件Vheader
<template>
<header class="header">
<div class="nav">
<div class="logo">
<img :src="imgSrc" />
</div>
<div class="info">
<button>注册</button>
<button>登陆</button>
</div>
</div>
</header>
</template>
<script>
import imgSrc from '../assets/logo.png'
export default {
name:'Vheader',
data(){
return {
imgSrc:imgSrc
}
},
}
</script>
<style scoped>
.header{
width: 100%;
height: 40px;
background-color: #fff;
box-shadow: 0 2px 4px 0 #c9c9c9; /* box-shadow是框边的阴影,更有立体感*/
}
.header .nav{
width: 980px;
height: 40px;
margin: 0 auto;
/*transparent透明*/
background-color: transparent;
}
.nav .logo{
width: 100px;
height: 40px;
float: left;
}
.logo img{
width: 40px;
height: 40px;
}
.nav .info{
float: right;
width: 200px;
height: 40px;
}
.info button{
width: 80px;
height: 40px;
float: left;
}
</style>
原作者:https://www.cnblogs.com/lxfpy/p/11045218.html

浙公网安备 33010602011771号