计算属性和监听属性,组件化开发之局部和全局组件,组件间通信之父传子(自定义属性),组件间通信之子传父(自定义事件),ref属性,数据总线,动态组件,slot插槽

1 计算属性和监听属性

1.1 计算属性

1 computed 对象写函数,函数就可以当属性使用
2 计算属性只有在它的相关依赖发生改变时才会重新求值
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <input type="text" v-model="myText"> ---->{{myText.substr(0, 1).toUpperCase() + myText.substr(1)}}
    <br><br>
    <input type="text" v-model="myText1"> ---->{{getText()}}
    <br><br>
    <input type="text" v-model="myText2"> ---->{{getName()}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            myText: '',
            myText1: '',
            myText2: '',
        },
        methods: {
            getText() {
                return this.myText1.substr(0, 1).toUpperCase() + this.myText1.substr(1)
            },
        },
        computed: { //计算属性
            getName() {
                return this.myText2.substr(0, 1).toUpperCase() + this.myText2.substr(1)
            },
        },

    })
</script>
</html>

重写过滤案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h1>过滤案例</h1>
            <input type="text" v-model="myText">
            <hr>
            <p v-for="item in newlist">{{item}}</p>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            myText: '',
            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
        },
        computed: {
            newlist() {
                return this.dataList.filter(item => {
                    return item.indexOf(this.myText) >= 0
                })
            },
        },
    })
</script>
</html>

1.2 监听属性

1 watch对象中写函数---》函数名就是data中得变量名,只要这个变量发生变化,就会触发该函数的执行
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <input type="text" v-model="myText" placeholder="......">
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            myText: '',
        },
        watch: {
            myText(val) {
                alert(val)
            },
        },
    })
</script>
</html>

2 组件化开发之局部和全局组件

# 组件是什么?有什么用
扩展 HTML 元素,封装可重用的代码,目的是复用
	-例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
	-组件把js,css,html放到一起,有逻辑,有样式,有html
    
# 定义全局组件
Vue.component('Child', {
        template: ``
          <div>
          <h1>我是一个组件--{{ myText }}</h1>
          <button @click="handleClick">点我看美女</button>
          <br>
          <input type="text" v-model="myText">
          <Jason></Jason>
          </div>`,
        data() {
            return {
                myText: '',
            }
        },
        methods: {
            handleClick() {
                alert('美女')
            }
        },
        components: {
            Jason: {
                template: `
                  <div>
                  <h1>我是局部组件--jason</h1>
                  </div>`,
            }
        }
    })


# 局部组件,写在Vue实力或者组件实例中
 components: {
            Lqz: {
                template: `
                  <div>
                  <h1>我是局部组件</h1>
                  </div>`,
            }
        }
        
########################################################################################
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <Child>

    </Child>
</div>
</body>
<script>
    // 定义全局组件
    Vue.component('Child', {
        template: `
          <div>
          <h1>我是一个全局组件{{ myText }}</h1>
          <button @click="click1">点完看牛马</button>
          <br>
          <input type="text" v-model="myText">
          <child1></child1>
          </div>
        `,
        data() {
            return {
                myText: '',
            }
        },
        methods: {
            click1() {
                alert('🐂🐎')
            },
        },
        components: {
            child1: {
                template: `
                  <div>
                  <h1>我是一个局部组件{{ myText }}</h1>
                  <input type="tel" v-model="myText">
                  </div>
                `,
                data() {
                    return {
                        myText: '',
                    };
                },

            }
        }
    })


    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {},
        computed: {},
    })
</script>
</html>

注意

# 1 自定义组件需要有一个root element,一般包裹在一个div中
# 2 父子组件的data,methods是无法共享
# 3 组件可以有data,methods,computed....,但是data 必须是一个函数

3 组件间通信之父传子(自定义属性)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    自定义属性: myname
    <Child :myname="name"></Child>
</div>
</body>
<script>
    // 全局组件
    Vue.component('Child', {
        template: `
          <div>
          <h1>我是一个组件--{{ myText }} 父组件传过来的{{ myname }}</h1>
          <button @click="click1">点击看牛马</button>
          <br>
          <input type="text" v-model="myText">
          </div>
        `,
        data() {
            return {
                myText: '',
            };
        },
        methods: {
            click1() {
                alert('🐂🐎')
            },
        },
        props: ['myname',]
    })
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'lcx'
        },
        methods: {},

    })
</script>
</html>

3.1 属性验证

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>父组件中输入值</h1>
    名字:<input type="text" v-model="name">
    <br>
    年龄:<input type="text" v-model.number="age">


    <h1>子组件中显示</h1>
    <hr>
    <Child :myname="name" :myage="age"></Child>

</div>
</body>

<script>

    //全局组件
    Vue.component('Child', {
        template: `
          <div>
          名字是:{{ myname }}
          <br>
          年龄是:{{ myage }}
          </div>`,
        // props:['myname',]
        props: {
            'myname': String,
            myage: Number
        }
    })


    // 局部组件只能在局部使用
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'lqz',
            age:19
        },


    })

</script>
</html>

4 组件间通信之子传父(自定义事件)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load static %}
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <h1>子组件中的myText的数据是:{{name}}</h1>
    <hr>
    <Child @myevent="click2"></Child>
</div>
</body>
<script>
    // 全局组件
    Vue.component('Child', {
        template: `
          <div>
          <input type="text" v-model="myText">
          <button @click="click1">点击向父组件传参数</button>
          </div>
        `,
        data() {
            return {
                myText: '',
            }
        },
        methods: {
            click1() {
                this.$emit('myevent', this.myText)
            },
        },
    })
    var vm = new Vue({
        el: '#app',
        data: {
            name: ''
        },
        methods: {
            click2(val) {
                this.name = val
            }
        },
    })
</script>
</html>

5 ref属性

# ref 属性是什么
ref放在普通标签上,拿到的是原生节点,原生dom操作
ref放在组件上,拿到的是组件对象,
	通过这种方式实现子传父(this.$refs.mychild.text)
  	通过这种方式实现父传子(调用子组件方法传参数)
    
<p ref='pp'></p>
<Child ref='cc'></Child>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <h1>我是父组件</h1>
    <p ref="pp">我是个p标签</p>
    <button @click="click1">点我或去子组件data</button>
    <p>名字:{{name}},年龄:{{age}}</p>
    <hr>
    <input type="text" v-model="myText">
    <button @click="click2">点击向子组件传值</button>
    <hr>
    <Child ref="child"></Child>
</div>
</body>
<script>
    Vue.component('Child', {
        template: `
          <div>
          <h1>我是子组件</h1>
          名字为:{{ name }}
          年龄为:{{ age }}
          </div>
        `,
        data() {
            return {
                name: '张三',
                age: 20,
            };
        },
        methods: {
            setvalue(val) {
                this.name = val
            }
        },
    })


    var vm = new Vue({
        el: '#app',
        data: {
            name: '',
            age: '',
            myText: '',
        },
        methods: {
            click1() {
                console.log(this.$refs)
                this.name = this.$refs['child'].name
                this.age = this.$refs['child'].age
            },
            click2() {
                this.$refs['child'].setvalue(this.myText)
            }
        },
    })
</script>
</html>

6 数据总线

# 不同层级的不通组件通信
	-数据总线
    -vuex--->状态管理器---》
    -cookie,localStorage,sessionStorage
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <child1></child1>
    <hr>
    <child2></child2>
</div>
</body>
<script>
    var bus = new Vue()

    Vue.component('child1', {
        template: `
          <div>
          <input type="text" v-model="myText">
          <button @click="click1">点我</button>
          </div>`,
        data() {
            return {
                myText: '',
            };
        },
        methods: {
            click1() {
                bus.$emit('suibian', this.myText)
            }
        },
    })

    Vue.component('child2', {
        template: `
          <div>
          接受到的数据是:{{ myText }}
          </div>`,
        data() {
            return {
                myText: '',
            };
        },
        mounted() {
            bus.$on('suibian', (name) => {
                this.myText = name
            })
        },
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {},
    })
</script>
</html>

7 动态组件

# 通过component配合is属性,决定显示的组件是哪个
# keep-alive 保证组件切换走后不被销毁
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
    <ul>
        <li @click="who='home'">首页</li>
        <li @click="who='goods'">商品</li>
        <li @click="who='order'">订单</li>
    </ul>
    <keep-alive>
        <component :is="who">

        </component>
    </keep-alive>

</div>
</body>
<script>

    Vue.component('home', {
        template: `
          <div>
          首页
          </div>`,
    })
    Vue.component('goods', {
        template: `
          <div>
          商品
          <input type="text">
          </div>`,
    })
    Vue.component('order', {
        template: `
          <div>
          订单
          </div>`,
    })


    var vm = new Vue({
        el: '#app',
        data: {
            who: 'home'
        },


    })

</script>
</html>

8 slot插槽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<home>
    <div><button>美女</button></div>

</home>

</div>
</body>
<script>

    Vue.component('home', {
        template: `
          <div>
          <input type="text">
          <hr>
          <slot></slot>
          <button>点我</button>

          </div>`,
    })


    var vm = new Vue({
        el: '#app',
        data: {
        },


    })

</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="app">
<home>
    <div slot="a">我是div</div>
    <img src="https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg" alt="" slot="b">

</home>

</div>
</body>
<script>

    Vue.component('home', {
        template: `
          <div>
          <input type="text">
          <hr>
          <slot name="a"></slot>
          navbar
          <slot name="b"></slot>
          <button>点我</button>

          </div>`,
    })


    var vm = new Vue({
        el: '#app',
        data: {
        },


    })

</script>
</html>
posted @ 2022-06-29 17:34  春游去动物园  阅读(20)  评论(0编辑  收藏  举报