Vue 组件实战

vue

axios实现数据请求、计算属性、监听属性、局部组件、全局组件、组件通信之父传子、组件通信之子传父、 ref属性(组件间通信)、动态组件和keep-alive

目录

  • Vue 组件

    • axios实现数据请求
    • 计算属性

      • 案例一:首字母大写
      • 案例二:过滤案例

    • 监听属性
    • 局部组件
    • 全局组件
    • 组件通信之父传子
    • 组件通信之子传父
    • ref属性(组件间通信)

      • 普通标签使用
      • 组件使用ref属性

    • 事件总线(不常用)
    • 动态组件和keep-alive

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()


计算属性

我们可以通过计算属性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>

我们可以发现只有和属性相关的才会打印,如果下面输入内容只是打印了普通函数,就算函数内和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>



监听属性

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>


局部组件

写在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实例托管的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>


组件通信之父传子

组件间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>


组件通信之子传父

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>


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>

组件使用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>

事件总线(不常用)

<!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 组件实战 的全部内容, 来源链接: utcz.com/z/381027.html

回到顶部