官方教程: https://cn.vuejs.org/v2/guidejavascript
let myComponent = Vue.extend({ template : '#my', // 此时的 #my 是id="my"的template标签 }); // 能够简化为 let myComponent = { template : '#my', data(){ // 此处的data必须是一个函数 } };
// 全局组件: 一次注册在全部的vue实例中(都可以使用 Vue.component('my-component',{ template : '#my-component', data () { // 此处的data必须是一个函数 }, }); // 局部组件: 只能在某一个vue实例中使用 const vm = new Vue({ 'el' : '#app', components : { 'my-component' : { template : '#my', data() { // 此处的data必须是一个函数 } }, } });
注: 为了保证各个组件的相互独立性,全部的组件中的data必须是一个函数html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="../node_modules/vue/dist/vue.js"></script> </head> <body> <!-- templates --> <template id="my"> <div> <p>这是本组件本身的数据: {{selfData}}</p> <p>这是父组件的数据: {{msg}}</p> </div> </template> <!-- /templates --> <!-- 使用组件 --> <div id="app"> <my-component :msg="message"></my-component> </div> <script> // 1.声明一个组件 let myComponent = Vue.extend({ template: '#my', props: ["msg"], // props 不单单能够是一个数组,也能够是一个对象 data() { return { selfData: "hello Vue", }; }, }); /** props 支持的类型========================= 1. 简单语法 Vue.component('props-demo-simple', { props: ['size', 'myMessage'] }) 2. 对象语法,提供校验 Vue.component('props-demo-advanced', { props: { // 检测类型 height: Number, // 检测类型 + 其余验证 age: { type: Number, default: 0, required: true, validator: function (value) { return value >= 0 } } } }); ==================================*/ // 2.在Vue实例中来注册组件 const vm = new Vue({ el: '#app', data: { message: 'hello world', }, components: { // 注册一个局部组件 'my-component': myComponent, // 注: 此时必须使用 - 分割单词,或者所有小写,不能使用驼峰式写法 } }); </script> <!-- 父组件 => 子组件: 在子组件中使用父组件的数据 1. 声明一个组件 2. 注册组件(全局或者局部组件均可以通讯) 3. 使用组件(my-component), 并在使用时绑定一个属性 :msg 4. 在子组件中用 props 来获取绑定的属性 props : ["msg"], 5. 测试,看是否可以成功传递值 --> </body> </html>
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- 使用组件 --> <my-component :msg="message" @custom_event="changeData"></my-component> </div> <!-- templates --> <template id="my"> <div> <p>{{msg}}</p> <p>{{selfData}}</p> <!-- <button @click="$emit('custom_enevt','args')">点我改变父组件的数据</button> --> <!-- 若是以为这种行内的触发知足不了复杂的逻辑需求,你也能够把这个触发写到这个组件的方法中 --> <button @click="triggerParent(10)">点我改变父组件的数据</button> </div> </template> <script> // 声明一个组件 let myComponent = Vue.extend({ template: '#my', props: ["msg"], data() { return { selfData: 'hello Vue', }; }, methods : { triggerParent(val){ // 触发父组件并传递一个参数,此时的val是click调用时传递的参数 this.$emit('custom_event', val); }, }, }); const vm = new Vue({ el: '#app', data: { message: 'hello world', }, methods: { changeData (val) { // 把message变成一个随机数链接上子组件传递的参数 this.message = val + Math.ceil(Math.random()*100); }, }, components: { // 注册一个局部组件 'my-component': myComponent, } }); </script> <!-- 因为vue为了保证各个组件的独立性,因此将各个组件的数据流向作成那单向数据流, 而这样,就只能父组件改变子组件的内容,而不能子组件改变父组件的内容 因此为了可以在子组件中改变父组件的数据,只有使用自定义事件系统 1. 声明一个组件 let myComponent = Vue.extend({...}); 2. 注册一个组件(全局,局部都行) 3. 使用组件 3.1) 绑定一个属性 :msg="message" 子组件能够用 props 来获取绑定的属性 3.2) 绑定一个自定义事件 @custom_event="changeData" 此时的custom_event是事件名称,changeData是methods中的方法 3.3) 子类想改变父类的数据,能够用$emit('事件名称')来触发父组件的事件,而后由父组件决定改变的规则,从而达到单向数据流的目的 3.4) 触发父类自定义事件 3.4.1) 行内触发 <button @click="$emit('custom_enevt','args')">点我改变父组件的数据</button> 此时的args是参数 3.4.2) 使用方法触发 <button @click="triggerParent(10)">点我改变父组件的数据</button> methods : { triggerParent(val){ // 触发父组件并传递一个参数,此时的val是click调用时传递的参数 this.$emit('custom_event', val); }, } --> </body> </html>
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue组件嵌套</title> <script src="./node_modules/vue/dist/vue.js"></script> <style> .cmpt1, .cmpt2 { color: #ffffff; padding: 15px; } .cmpt1 { background: #272822; } .cmpt2 { background: #265a88; } </style> </head> <body> <div id="app"> <my-component @custom_event="changeData" :msg="message"></my-component> </div> <!-- templates --> <template id="my"> <div> <one :msg="msg" :name="name"></one> <two :msg="msg" @test_event="changeMess"></two> </div> </template> <!--one--> <template id="one"> <div class="cmpt1"> <p>这是组件1</p> <p>这是二级传递: hello {{msg}}!!! </p> <p>这是三级传递: what's your name? my name is {{name}}</p> </div> </template> <!--two--> <template id="two"> <div class="cmpt2"> <p>这是组件2</p> <p> hello {{msg}} </p> <p> <button @click="changePrentData(10)">点我改变父组件数据</button> </p> </div> </template> <script> // 声明一个子组件 let one = Vue.extend({ template: '#one', props: ["msg", "name"], }); // 声明一个子组件 let two = Vue.extend({ template: '#two', props: ["msg"], methods: { changePrentData(val) { let m = Math.ceil(Math.random() * val); // this.$emit('custom_event', m); this.$emit('test_event', m); } }, }); // 声明一个父组件 let myComponent = Vue.extend({ template: '#my', props: ["msg"], methods: { changeMess(val){ this.$emit('custom_event',val); } }, components: { 'one': one, 'two': two }, data() { return { name: 'Tom', }; } }); const vm = new Vue({ el: '#app', data: { message: 'world', }, methods: { changeData(val) { this.message = "这是改变后的message,喜欢吗? " + val + " 是点击是传递的参数"; } }, components: { // 注册一个局部组件 'my-component': myComponent, } }); </script> <!-- 组件嵌套时,最底层的组件想要与最顶层的组件通讯,必须一层一层向上传递 --> </body> </html>
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>蒙版效果</title> <style> * { margin: 0; padding: 0; } html, body { width: 100%; height: 3000px; /* 为了测试滚动 */ } #alert-panel { width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); position: absolute; top: 0; left: 0; /*display: none;*/ } #alert-panel #login { width: 500px; height: 300px; background: #000000; position: fixed; top: 50%; left: 50%; margin-left: -250px; margin-top: -180px; } #close-alert-panel { background: #000; color: #ffffff; border: none; width: 30px; height: 30px; float: right; } #close-alert-panel:hover { background: #f00; } </style> <!--javascript--> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- 当点击button的时候,显示模态框,在模态框中点击关闭按钮时,关闭模态框 --> <button id="btn" @click="showDialog">点击登录</button> <modal :is-hide-dialog="!isHide" @close="closeModal"></modal> </div> <template id="dialog"> <div id="alert-panel" v-show="isHideDialog"> <div id="login"> <button id="close-alert-panel" @click="$emit('close')">×</button> </div> </div> </template> <script> // 声明一个组件 let modal = Vue.extend({ template: '#dialog', props: ["isHideDialog"], }); const vm = new Vue({ el: '#app', data: { isHide: true, }, methods: { showDialog() { this.isHide = false; }, closeModal() { this.isHide = true; } }, components: { 'modal': modal } }); </script> </body> </html>
注: 若是ref放在组件上,那么经过$refs拿到的不是组件的dom而是这个组件vue
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- 注: 若是ref放在组件上,那么经过$refs拿到的不是组件的dom而是这个组件 --> <load ref="load"></load> </div> <!--templates--> <template id="load"> <div v-if="isShow"> <p>玩命加载中...</p> </div> </template> <!-- JavaScript --> <script> let load = Vue.extend({ template: '#load', data () { return { isShow: true, } }, methods: { hide(){ this.isShow = false; console.log("我被调用了,这个组件已经被隐藏了"); } }, }); const vm = new Vue({ el: '#app', components: { "load": load, }, mounted () { // 当vm实例挂载的时候,就调用子组件的方法,隐藏加载组件 this.$refs.load.hide(); } }); </script> </body> </html>
默认在子组件中不能修改父组件传递的值,若是非要
加工父组件传递过来的数据,可使用 computed 属性或者 data()
来加工父组件传递的值,此种方式虽然可以加工了父组件
传递的数据,可是不会改变父组件的数据,保证了各个组件的独立性(单向数据流)java
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <my-comp :name="message"></my-comp> </div> <!--templates--> <template id="my"> <div> <p>父组件原数据: {{name}}</p> <p>改变后的数据: {{myName}}</p> <p>改变后的数据: {{myName2}}</p> </div> </template> <!-- JavaScript --> <script> // make a component let myComponent = Vue.extend({ template: '#my', props: ["name"], // 要求: 在子组件中,将父组件传递的值拼接一个随机数 // 方式一:使用计算属性来改变父组件传递的值 computed:{ myName(){ return this.name + Math.random(); } }, // 方式二:使用data()方法来改变父组件传递的值(局部变量) data(){ return { "myName2" :this.name + Math.random(), } }, }); const vm = new Vue({ el: '#app', data: { message: 'hello world', }, components: { // register a local component "my-comp": myComponent, }, }); </script> </body> </html>