Vue 组件实战

  • Vue 组件实战已关闭评论
  • 170 次浏览
  • A+
所属分类:Web前端
摘要

我们可以通过计算属性computed来缓存计算,什么意思呢?在Vue中我们可以使用插值来展示数据,插值的普通函数,只要页面一刷新,函数就会重新运算,不管和函数有关没关的值都会变,函数也会重新计算,导致运行效率降低;

Vue 组件

Vue 组件实战

axios实现数据请求

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="./js/vue.js"></script>     <script src="https://unpkg.com/axios/dist/axios.min.js"></script>  </head> <body> <div id="app">     <ul>         <li v-for="film in films_list">             <p>电影名字是:{{film.name}}</p>             <img :src="film.poster" alt="" width="100px" height="150px">             <p>电影介绍:{{film.synopsis}}</p>         </li>     </ul>  </div>  </body> <script>      var vm = new Vue({         el: '#app',         data: {             films_list:[]         },         created() {             axios.get('http://127.0.0.1:5000/films').then(res => {                 console.log(res.data)                 this.films_list=res.data.data.films             })          }     }) </script> </html> 
from flask import Flask,make_response,jsonify  app=Flask(__name__) @app.route('/films') def films():     import json     with open('./movie.json','r',encoding='utf-8') as f:         res=json.load(f)     obj = make_response(jsonify(res))     obj.headers['Access-Control-Allow-Origin']='*'     return obj  if __name__ == '__main__':     app.run() 

Vue 组件实战


计算属性

我们可以通过计算属性computed来缓存计算,什么意思呢?

在Vue中我们可以使用插值来展示数据,插值的普通函数,只要页面一刷新,函数就会重新运算,不管和函数有关没关的值都会变,函数也会重新计算,导致运行效率降低;

那么我们可以将自定义函数写在computed中来控制,把函数当成属性来用,调用不需要加括号,只有这个函数使用的属性(变量)发生变化,函数才重新运算,这样做可以减轻压力,减少资源浪费

案例一:首字母大写

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>计算属性</title>     <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>     <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">     <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>     <script src="./js/vue.js"></script> </head> <body> <div id="app">     <div style="font-size: 20px">         输入内容:<input type="text" v-model="mytext"> ----》 {{mytext.substring(0,1).toUpperCase()+mytext.substring(1)}}         <br><br>         <p>函数绑定(会刷新页面,也不推荐):<input type="text" :value="getName()"></p>         <p>计算属性(推荐):<input type="text" :value="getName1"></p>     </div>      <hr>     <div style="font-size: 20px">          <p>输入内容:<input type="text" v-model="mytext1"> -----》{{mytext1}}</p>     </div> </div> </body> <script>     var vm = new Vue({         el: '#app',         data: {             mytext: '',             mytext1:''         },         methods:{             getName(){                 console.log('函数方式,我执行了')                 return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)             }         },         //计算属性         computed:{             getName1(){                 console.log('计算属性,我执行了')                 return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)             }          }     }) </script> </html> 

Vue 组件实战

我们可以发现只有和属性相关的才会打印,如果下面输入内容只是打印了普通函数,就算函数内和mytext1不相关

案例二:过滤案例

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>过滤案例</title>     <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box">     <p><input type="text" v-model="myText"  placeholder="请输入要筛选的内容:"></p>     <ul>         <li v-for="data in newList">{{data}}</li>     </ul> </div> </body> <script>     var vm = new Vue({         el: '#box',         data: {             myText: '',             dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],         },          computed:{              newList(){                 var _this = this                 console.log('执行了',_this)                  var datalist2 = _this.dataList.filter(function(item){                     console.log(_this)                      return item.indexOf(_this.myText) > -1                  })                 return datalist2              }         }     }) </script> </html> 

Vue 组件实战


监听属性

watch来设置监听属性,当mytext发生变化,就会执行和mytext绑定的函数方法

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="./js/vue.js"></script> </head> <body> <div id="app">      <input type="text" v-model="mytext">--->{{mytext}}   </div>  </body> <script>     var vm = new Vue({         el: '#app',         data: {             mytext: '',         },         watch: {             // 只要mytext发生变化,就会执行该函数             mytext: function () {                 console.log('我变化了,执行')              }         }       }) </script> </html> 

Vue 组件实战


局部组件

写在components里的是局部组件,位置被限制,只能再局部使用

比如如下例子中,Top组件只能在只能再id为app的标签(div)内使用, Top组件内如果想再定义子组件,只能在该组件内的template中的div内使用

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="./js/vue.js"></script> </head> <body> <div id="app">     <Top></Top>     <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>     <Bottom></Bottom> </div>  </body> <script>     var vm = new Vue({         el: '#app',         data: {},         // 定义再这里面的叫局部组件,只能再局部使用,只能再id为app的标签内使用         components: {             'Top': {                 //写在一个div里                 template: `                     <div>                         <h1 style="background: pink;font-size: 60px;text-align: center">{{name}}</h1>                         <hr>                         <button @click="handleC">点我看美女</button>                     </div>                 `,                 //data是函数,可以设置返回值                 data() {                     return {                         name: "我是头部"                     }                 },                 methods: {                     handleC() {                         alert('美女')                     }                 },             },             'Bottom': {                 template: `                     <div>                         <hr>                         <h1 style="background: green;font-size: 60px;text-align: center">{{name}}</h1>                      </div>                 `,                 data() {                     return {                         name: "我是尾部"                     }                 },              },          },       }) </script> </html> 

Vue 组件实战


全局组件

任意位置都可以使用但是也得是在vue实例托管的div范围内

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="./js/vue.js"></script> </head> <body> <div id="app">     <top></top>   </div>  </body> <script>     // 定义全局组件,任意位置都可以用,局部内也可以使用     Vue.component('top', {             template: `                 <div>                     <h1 style="background: pink;font-size: 60px;text-align: center">{{name}}</h1>                     <hr>                     <button @click="handleC">点我看美女</button>                 </div>             `,             data() {                 return {                     name: "我是头部"                 }             },             methods: {                 handleC() {                     alert('美女')                 }             },          },)      var vm = new Vue({         el: '#app',     }) </script> </html> 

Vue 组件实战


组件通信之父传子

组件间data数据不同享,数据传递,如果我们想从父组件传递到子组件数据通过props自定义属性来实现,比如如下例子:

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>     <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">     <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>     <script src="./js/vue.js"></script> </head> <body> <div id="app">     子组件显示:<top :value="handleName"></top>     <hr>     父组件输入内容:<input type="text" v-model="handleName">  </div>  </body> <script>      Vue.component('top', {         template: ` <div>                     <h1 style="background: tomato;font-size: 30px;text-align: center">{{value}}</h1>                     </div>             `,         // 必须叫props,数组内放自定义属性的名字         props:{             value: String,  // key是自定义属性名,value是类型名,如果是别的类型就报错         },         //props也可以写成数组的形式,不带验证功能         // props:['value',]     })     var vm = new Vue({         el: '#app',         data: {             handleName: ''         }     }) </script> </html> 

Vue 组件实战


组件通信之子传父

ps:Vue内置的对象都以$xx出现

我们可以通过自定义事件来实现子组件向父组件传递数据,在子组件中使用$emit('自定义事件',参数)来实现

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>     <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">     <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>     <script src="./js/vue.js"></script> </head> <body> <div id="app"> <top @myevent="handleRecv"></top>     <hr>   <h1 style="background: green;font-size: 60px;text-align: center">父组件</h1>  <p>接收子组件发送的数据:{{childText}}</p> </div>  </body> <script>      Vue.component('top', {         template: ` <div>                         <h1 style="background: tomato;font-size: 60px;text-align: center">{{myheader}}</h1>                         <p>子组件输入内容:<input type="text" v-model="text"></p>                         <p><button class="btn-success"  @click="handleSend">向父组件发送数据</button></p>                     </div>             `,         data(){             return {                 myheader:'子组件',                 text:''             }         },         methods:{             handleSend(){                 //myevent是自定义事件,代表将子组件的text交给myevent事件处理                 this.$emit('myevent',this.text)             }         }      })     var vm = new Vue({         el: '#app',         data: {             //接收子组件的数据             childText:''         },         methods: {             handleRecv(data){                 // 接收参数,赋值给父组件的childText                 this.childText=data             }         }     }) </script> </html> 

Vue 组件实战


ref属性(组件间通信)

普通标签使用

普通标签使用ref属性,通过$refs获取到的就是ref属性所在的标签,获取到的是一个对象,如果多个标签写了ref属性,那么就将所有带ref属性的标签弄到一个对象中,可以对html进行操作设置等,如下示例:

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>     <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">     <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>     <script src="./js/vue.js"></script> </head> <body> <div id="app">     <h1 style="align-content: center">普通标签使用ref</h1>     <p><input type="text" ref="myinput"></p>     <p><img src="" height="100px" width="100px" ref="myimg"></p>     <p><button @click="handleC">点我</button> </p> </div> </body> <script>      let vm = new Vue({         el: '#app',         data: {              text:''         },         methods: {             handleC(){                 console.log('我被点了')                 console.log(this.$refs)  // 是所有标签写了ref属性的对象{myinput:真正的标签,myimg:真正的标签}                 console.log(this.$refs.myinput.value)                 //设置值                 this.$refs.myinput.value='HammerZe'                 //设置src属性,显示图片                 this.$refs.myimg.src='https://img0.baidu.com/it/u=3608430476,1945954109&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=494'             }         }     }) </script> </html> 

Vue 组件实战

组件使用ref属性

ref属性,如果放在组件上,就是当前组件对象

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>     <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">     <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>     <script src="./js/vue.js"></script> </head> <body> <div id="app"> <!-- 组件使用ref属性   --> <top ref="top"></top> <p>通信:<input type="text" v-model="text"></p> <p>父组件按钮:<button @click="handleC">点我</button></p> </p> </div> </body> <script>    Vue.component('top', {         template: `             <div>                 <h1>{{myheader}}</h1>                 <p>子组件按钮:<button @click="handleC">点我看美女</button></p>                 <hr>             </div>         `,         data() {             return {                 myheader: "头部",             }         },         methods:{             handleC(){                 alert("美女")             }         }        },)     let vm = new Vue({         el: '#app',         data: {              text:''         },         methods: {         //放在组件上         handleC() {              console.log(this.$refs.top) //VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}             /*子传父*/             // 父组件拿子组件的值             console.log(this.$refs.top.myheader)             // this.text=this.$refs.top.myheader             // 父组件调用子组件的方法             this.$refs.top.handleC()              /*父传子*/             this.$refs.top.myheader=this.text         }         }     }) </script> </html>  

Vue 组件实战

事件总线(不常用)

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="js/vue.js"></script> </head> <body> <div id="box">     <child1></child1>     <child2></child2> </div> </body> <script>     var bus=new Vue() //new一个vue的实例,就是中央事件总线     Vue.component('child1', {         template: `<div>             <input type="text" ref="mytext">             <button @click="handleClick">点我</button>         </div>`,         methods:{             handleClick(){                 bus.$emit('suibian',this.$refs.mytext.value) //发布消息,名字跟订阅消息名一致             }         }     })     Vue.component('child2', {         template: `<div>                     <div>收到的消息 {{msg}}</div>                     </div>`,         data(){             return {msg:''}         },         mounted(){             //生命周期,当前组件dom创建完后悔执行             console.log('当前组件dom创建完后悔执行')             //订阅消息             bus.$on('suibian',(item)=>{                 console.log('收到了',item)                 this.msg=item             })         }     })     var vm = new Vue({         el: '#box',         data: {},         methods: {             handleClick() {                 console.log(this)                 //this.$refs.mytext 获取到input控件,取出value值                 console.log(this.$refs.mytext.value)                 console.log(this.$refs.mychild.text)                 // this.$refs.mychild.add()                 this.$refs.mychild.add('传递参数')              }         }      }) </script> </html> 

动态组件和keep-alive

动态组件:实现点击不同的连接显示不同的页面,实现跳转,使用component标签,用is属性绑定,指定哪个显示哪个

keep-alive:通过keep-alive标签实现组件不销毁,保留原来输入的内容

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <script src="./js/vue.js"></script> </head> <style>     #menu {         font-size: 18px;         font-weight: bold;     }      #menu li {         text-decoration: none; /*去掉前面的圆点*/         list-style: none;         float: left;         margin-right: 20px;      }  </style> <body> <div id="app">     <ul id="menu">         <li @click="changeC('index')">首页</li> &nbsp;         <li @click="changeC('order')" >订单</li>         <li @click="changeC('good')">商品</li>     </ul>       <keep-alive>         <component :is='who'></component>     </keep-alive>   </div>  </body> <script>     //三个组件     Vue.component('index', {         template: `             <div style="overflow:hidden;">                 <h1>首页内容</h1>             </div>         `,     },)     //保留输入的订单信息     Vue.component('order', {         template: `             <div>                 <h1>订单内容</h1>                 请输入要查询的订单:<input type="text">             </div>         `,     },)     Vue.component('good', {         template: `             <div>                 <h1>商品内容</h1>             </div>         `,     },)      var vm = new Vue({         el: '#app',         data: {             //默认显示index             who: 'index'          },         methods: {             changeC(data) {                 this.who = data             }         }      }) </script> </html> 

Vue 组件实战