Vue 小实例 - 组件化 、cli 工程化
1. 组件化 (父子组件通信: 父 - 子 :props 数组 子 - 父 : 子层触发事件,调用 $emit 触发父层对应自定义事件,可函数处理传参 / $event 获取)
html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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>Document</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <input v-model="inputVal" /> <button @click="addEle">add</button> <ul> <todo-list v-for="(item,index) in items" :key="index" :content="item" :index="index" @del="removeHandle" ></todo-list> <!-- <li v-for="item in items">{{item}}</li> --> </ul> </div> <script src="js/js.js"></script> </body> </html>
js
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Vue.component('todo-list',{ props:['content','index'], template:'<li @click="removeCall">{{content}}</li>', methods:{ removeCall:function(){ this.$emit('del',this.index) } } }) // var TodoList={ // props:['content','index'], // template:'<li @click="removeCall">{{content}}</li>', // methods:{ // removeCall:function(){ // this.$emit('del',this.index) // } // } // } var app=new Vue({ el:'#app', // components:{ // 'todo-list':TodoList // }, data:{ items:['wj','xiaoxiao','six'], inputVal:'' }, methods:{ addEle:function(){ this.items.push(this.inputVal); this.inputVal=''; }, removeHandle:function(index){ this.items.splice(index,1) } } })
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
new Vue({ router, store, //components: { App } vue1.0的写法 render: h => h(App) vue2.0的写法 }).$mount('#app')
1.1 官网实例写法 (父子组件通信)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <ol id="app"> <div :style="{ fontSize: postFontSize + 'em' }"> <blog-post v-for="(post,index) in posts" v-on:enlarge-text="postFontSize += $event" v-bind:key="post.id" v-bind:post="post" :index="index" @del="removeHadle"> </blog-post> </div> </ol> <script> Vue.component('blog-post', { props: ['post', 'index'], template: ` <div class="blog-post"> <h3 @click="remove(index)">{{ post.title }}</h3> <div v-html="post.content"></div> <button v-on:click="$emit('enlarge-text',0.5)"> Enlarge text </button> </div>`, methods: { remove: function (index) { this.$emit('del', index) } } }) var app = new Vue({ el: '#app', data: { posts: [{ id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ], postFontSize: 1 }, methods: { removeHadle: function (index) { this.posts.splice(index, 1) } } }) </script> </body> </html>
1.2 自定义双向绑定组件写法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <ol id="app"> <!-- <input v-model="searchText"> --> <!-- <input v-bind:value="searchText" v-on:input="searchText = $event.target.value"> --> <!-- <custom-input v-bind:value="searchText" v-on:input="searchText = $event"></custom-input> --> <custom-input v-model="searchText"></custom-input> </ol> <script> Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` }) var app = new Vue({ el: '#app', data: { searchText: 'hello' } }) </script> </body> </html>
1.3 兄弟组件通信 : 由于 Vue 实例实现了一个事件分发接口,可以通过实例化一个空的 Vue 实例,组件中使用 $emit
, $on
, $off
分别来分发、监听、取消监听事件。
类似 jq trigger 的自定义事件及其触发使用方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <p style="margin-bottom:50px;">{{msg}}</p> <post-wrap></post-wrap> <get-wrap></get-wrap> </div> <script> var bus = new Vue(); Vue.component("post-wrap", { template: ` <div> <h1>post-wrap</h1> <input type="text" v-model="postMes"/> <button @click="eventPost">post</button> </div> `, data: function () { return { postMes: "" } }, methods: { eventPost: function () { bus.$emit("eventGet", this.postMes); this.postMes = ""; } } }) Vue.component("get-wrap", { template: ` <div> <h1>get-wrap</h1> <p v-for="item in items">{{item}}</p> </div> `, data: function () { return { items: [] } }, mounted: function () { bus.$on("eventGet", (item) => { this.items.push(item); }) } }) new Vue({ el: "#app", data: { msg: "Hello" } }) </script> </body> </html>
1.3.1 兄弟组件通信(更合理的写法 : 销毁时清除对应事件)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <p style="margin-bottom:50px;">{{msg}}</p> <post-wrap></post-wrap> <get-wrap></get-wrap> </div> <script> var bus = new Vue(); var postWrap={ template: ` <div> <h1>post-wrap</h1> <input type="text" v-model="postMes"/> <button @click="eventPost">post</button> </div> `, data: function () { return { postMes: "" } }, methods: { eventPost: function () { bus.$emit("eventGet", this.postMes); this.postMes = ""; } } }; var getWrap= { template: ` <div> <h1>get-wrap</h1> <p v-for="item in items">{{item}}</p> </div> `, data: function () { return { items: [] } }, mounted: function () { bus.$on("eventGet", this.eventMyGet) }, beforeDestroy: function () { bus.$off('eventGet', this.eventMyGet) }, methods: { eventMyGet: function (item) { this.items.push(item); } } }; Vue.component("post-wrap",postWrap ) Vue.component("get-wrap",getWrap) new Vue({ el: "#app", data: { msg: "Hello" } }) </script> </body> </html>
2. cli 工程化
2.1 vue-cli 环境搭建
安装完 node 后,
npm install --global vue-cli
vue init webpack my-project
cd my-project
npm run dev
2.2 代码编辑 ( src 目录下修改 )
文件名称修改 APP - TodoList HelloWord - TodoItem
main
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import TodoList from './TodoList' Vue.config.productionTip = false /* eslint-disable no-new */ // 模板渲染内容:template > html new Vue({ el: '#app', components: { TodoList }, template: '<TodoList />' })
TodoList
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div id="app"> <input v-model="inputVal"> <button @click="addEle">add</button> <ul> <todo-list v-for="(item,index) in items" :key="index" :content="item" :index="index" @del="removeHandle" ></todo-list> </ul> </div> </template> <script> import TodoList from "./components/TodoItem"; export default { name: "App", // template:'<div id="app"> ... </div>', components: { "todo-list": TodoList }, data() { // () 、 return 、 {}、 msg 前后空格 return { items: ["wj", "xiaoxiao", "six"], inputVal: "" }; }, methods: { addEle: function() { if (this.inputVal === "") { return; } this.items.push(this.inputVal); this.inputVal = ""; }, removeHandle: function(index) { this.items.splice(index, 1); } } }; </script> <style> #app { font-size: 36px; } </style>
TodoItem
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <li @click="removeCall">{{content}}</li> </template> <script> export default { name: "todo-list", props: ["content", "index"], methods: { removeCall: function() { this.$emit("del", this.index); } } }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> * { color: #42b983; } </style>
3.扩展
Vue中使用 transition标签或transition-group标签
Put the favorites in the favorites and empty the favorites.