Vue的组件和表单
一.表单输入绑定
1.数据的双向绑定
v-model 指令在表单 <input>
、<textarea>
及 <select>
元素上创建双向数据绑定
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <label for="username">用户名:</label> <input type="text" v-model="msg" id="username"> <p>{{ msg }}</p> <textarea placeholder="add multiple lines" v-model='msg'></textarea> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> <br> <!--多个复选框 使用列表保存--> <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> <br> <select v-model="selected"> <option disabled value="">请选择</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> <!--懒监听--> <input v-model.lazy="msg" > <!--数字显示--> <input v-model.number="age" type="number"> <!--清除前后空格--> <input v-model.trim="msg"> </div> <script src="vue.js"></script> <script> new Vue({ el: '#app', data() { return { msg: 'alex', checked: false, checkedNames: [], selected:'', age:0 } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <input type="text" :value="msg" @input = 'changeHandler'> <p>{{ msg }}</p> </div> <script src="vue.js"></script> <script> //Object.definePropty() new Vue({ el:'#app', data(){ return { msg:'alex' } }, methods:{ changeHandler(e){ this.msg = e.target.value } } }) </script> </body> </html>
二.组件
1.全局组件使用
Vue.component('全局组件的名字',{
跟new Vue() 实例化对象中的options是一样,但是要注意:
不管是公共组件还是局部组件 data必须是个函数 函数一定要返回 {}
})
<slot> 元素作为承载分发内容的出口
2.局部组件的使用
油诗: 声子 挂子 用子
声子
let App = { data(){ return { } }, template:`<div> </div>` }
挂子
挂载哪个组件,这个组件就是我的父组件
template中的模板一定要有一个根元素
{ .... template:`<App/>` components:{ //挂子 App } }
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> {{ msg }} </div> <script src="vue.js"></script> <script> //如果仅仅是实例化vue对象中 既有el 又有template,如果template中定义模板的内容 // 那么template模板的优先级大于el // App header aside content // 1.声子 Vue中 组件的名字 首字母要大写 跟标签区分 组件中的data必须是个函数 一定要有返回值 let App = { data(){ return { text:"我是日天" } }, template:` <div id="a"> <h2>{{ text }}</h2> </div> `, methods:{ } } new Vue({ el: '#app', data() { return { msg:'alex' } }, //3 用子 template: ` <div class="app"> <App></App> </div> `, components:{ //2.挂子 //如果key和value一样 可以只写一个 //App:App App } }) </script> </body> </html>
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <App></App> </div> <script src="vue.js"></script> <script> //如果仅仅是实例化vue对象中 既有el 又有template,如果template中定义模板的内容 // 那么template模板的优先级大于el //第一个参数是组件的名字,第二个参数 options参数 它是全局组件 // <slot></slot> slot是vue中提供的内容组件 它会去分发 内容 Vue.component('VBtn',{ data(){ return { } }, template:`<button> <slot></slot> </button>` }) // App header Vaside Vcontent // 1.声子 Vue中 组件的名字 首字母要大写 跟标签区分 组件中的data必须是个函数 一定要有返回值 let Vheader = { data(){ return { } }, //template定义模板的内容 // Component template should contain exactly one root element template:` <div> <h2>日天</h2> <h2>日天</h2> <VBtn>登录</VBtn> <VBtn>注册</VBtn> <VBtn>按钮</VBtn> <VBtn>提交</VBtn> </div> ` } let App = { data(){ return { text:"我是日天" } }, template:` <div id="a"> <h2>{{ text }}</h2> <Vheader></Vheader> <VBtn>删除</VBtn> <br> </div> `, methods:{ }, components:{ Vheader } } new Vue({ el: '#app', data() { return { msg:'alex' } }, template:`<App />`, components:{ //2.挂子 //如果key和value一样 可以只写一个 //App:App App } }) </script> </body> </html>
3.父子组件传值
父向子传值
1.在子组件中 使用props声明 可以直接在子组件中任意使用
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <App></App> </div> <script src="vue.js"></script> <script> Vue.component('VBtn', { data() { return {} }, template: `<button> {{ id }} </button>`, props:['id'] }) let Vheader = { data() { return {} }, //只要声明了父组件的属性,就可以使用 props: ['msg', 'post'], template: ` <div class="child"> <h2>日天</h2> <h2>{{ msg }}</h2> <h3>{{ post.title}}</h3> <VBtn v-bind:id = 'post.id'></VBtn> </div> ` } let App = { data() { return { text: "我是父组件的数据", post: { id: 1, title: 'My Journey with Vue' } } }, template: ` <div id="a"> <Vheader :msg = 'text' v-bind:post = 'post'></Vheader> </div> `, methods: {}, components: { Vheader } } new Vue({ el: '#app', data() { return { msg: 'alex' } }, template: `<App />`, components: { App } }) </script> </body> </html>
子向父传值
1、子组件中 通过$emit()触发父组件中自定义的事件
2、父组件中声明自定义的事件介绍
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <App></App> </div> <script src="vue.js"></script> <script> Vue.component('VBtn', { data() { return {} }, template: `<button @click = 'clickHandler'> {{ id }} </button>`, props:['id'], methods:{ clickHandler(){ //每个组件中的this指的是当前组件对象 console.log(this); this.id++; // this.$emit('父组件声明自定义的事件','传值'); this.$emit('clickHandler',this.id); } } }) let Vheader = { data() { return {} }, //只要声明了父组件的属性,就可以使用 props: ['msg', 'post'], template: ` <div class="child"> <h1>我是header组件</h1> <h2>日天</h2> <h2>{{ msg }}</h2> <h3>{{ post.title}}</h3> <VBtn v-bind:id = 'post.id' @clickHandler="clickHandler"></VBtn> </div> `, methods:{ clickHandler(val){ alert(val); this.$emit('fatherHandler',val) } }, created(){ console.log(this); }, } let App = { data() { return { text: "我是父组件的数据", post: { id: 1, title: 'My Journey with Vue' } } }, template: ` <div id="a"> 我是父组件的 {{post.id}} <Vheader :msg = 'text' v-bind:post = 'post' @fatherHandler = 'father_handler'></Vheader> </div> `, methods: { father_handler(val){ console.log(val); this.post.id = val; } }, components: { Vheader }, created(){ console.log(this); }, } new Vue({ el: '#app', data() { return { msg: 'alex' } }, created(){ console.log(this); }, template: `<App />`, components: { App } }) </script> </body> </html>
4.平行组件传值
使用$on()和$emit() 绑定的是同一个实例化对象
1、B组件中要使用$on(‘事件的名字’,function(){})
2、A组件中使用$emit('事件的名字',值)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <App/> </div> <script src="vue.js"></script> <script> let bus = new Vue(); //A===》B B要声明事件 $on('事件的名字',function(val){}) A要触发事件 $emit('A组件中声明的事件名','值') //前提 这两个方法必须绑定在同一个实例化对象(bus) Vue.component('Test2', { data() { return { text:'' } }, template: ` <h2>{{ text }}</h2> `, methods: { }, created(){ bus.$on('testData', (val)=> { alert(val); this.text = val; }) } }) Vue.component('Test', { data() { return { msg: '我是子组件的数据' } }, props:['txt'], template: ` <button @click = 'clickHandler'>{{ txt }}</button> `, methods: { clickHandler() { bus.$emit('testData',this.msg) } } }) let Vheader = { data() { return { txt:'wusir' } }, template: ` <div class="header"> <Test :txt = 'txt'/> <Test2 /> </div> ` } let App = { data() { return {} }, template: ` <div class="app"> <Vheader /> </div> `, components: { Vheader } } new Vue({ el: '#app', data() { return {} }, components: { App } }) </script> </body> </html>