组件其他

根组件和组件的一些问题归总:
	1.new Vue() el:'xx' 管理的Div 就算根组件
	2.父子组件的数据是无法共享的
	3.组件有自己的html,css,js
	4.在组件中,this代指当前组件
	5.组件中data是一个函数,需要有返回值(return) 并且返回的是'对象'!
	6.全局组件内部的组件就是局部组件
	7.全局组件需要定义在Vue实例上面
	

组件间通信之父传子

组件间数据并不共享,需要进行数据传递!
父传子:使用自定义属性方法
在子组件标签上自定义绑定属性,并且在子组件props数组/对象中进行注册

image

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>
<div id="app">
    <child :fage="fage" :fname="fname"></child>
</div>
</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{fname:'程潇',fage:18},
        methods:{},
        components: {
            'child':{
                template:`
           <div>
           <h1>子组件</h1>
           <br>
          名字:{{ fname }}<--->年龄:{{ fage }}
          </div>`, // 子组件的数据可以通过模板语法放入template层
                data(){
                    return{
                        cname:'刘亦菲'
                    }
                },
                // props: ['fage'] //如果我们需要父传给子数据 就需要将传输的数据变量名注册在props数组中
                props: {fage: String, fname: String},
                // props也支持对象方法:可以指定传输数据的数据类型,如果不符合对应的数据类型,就会报错,但是不影响显示
            }
        }
    })
</script>
</html>

父传子步骤

1.在父组件中将需要传递的数据通过props数组/对象注册
2.子组件标签中自定义绑定属性 :fage="fage",绑定的就是需要传递的数据
3.组件通过模板语法调用即可

组件间通信之子传父

# 通过在子标签编写自定义事件,并且在父组件中编写函数即可

流程详解
image

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>
<div id="app">
    <div>
        <h2>父组件----子组件传递来的数据:{{fname}}</h2>

        <child @myevent="handleEvent"></child>
    </div>
</div>
</body>
<script>
    Vue.component('child',{
        template:`
<div>
<h2> 子传父演示</h2>
    <p><button @click="handleSend">点击提交数据</button></p>
</div>`,
        data(){
            return{
                cname:'小蜜瓜'
            }
        },
        methods:{
            handleSend() {
                this.$emit('myevent',this.cname)
            }
        }
    })
    // 父组件
    var vm = new Vue({
        el:'#app',
        data:{
            fname:''
        },
        methods:{
            handleEvent(cname){
                console.log(cname)
                this.fname = cname
            }
        }
    })
</script>
</html>

image

案例演示
通过在子组件中输入框输入内容,点击按钮传输到父组件中
image

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>

<div id="app">
<h2>子传父数据展示>>>>>{{fText}}</h2>
    <child @cevent="handleRecv"></child>
</div>


</body>
<script>
    Vue.component('child',{
        template:`
        <div>
<h2>子传父案例演示~</h2>
     <p><input type="text" v-model="cText">请输入内容</p>
    <p> <button @click="handleSend">点击传输数据到父组件~</button></p>
</div>
        `,data(){
            return{
                cText:''
            }
        },
        methods:{
            handleSend(){
                console.log(this.cText)
                this.$emit('cevent',this.cText)
            }
        }
    })


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

子传父步骤

1.在子组件编写点击事件
2.在methods中通过this.$emit()方法将需要传递给父组件的数据编写进去
3.在 子组件标签中 自定义事件,绑定父组件函数!
4.父组件函数接收this.$emit()方法传递过来的参数

ref属性(也可以实现组件间通信:父和子通信都可以实现~)

  • ref放在标签上 拿到的是原生的DOM节点(标签对象)
  • ref放在组件上,拿到的是组件对象,对象中的数据,函数(方法)都可以直接使用
ref 属性可以更方便拿到实现父子通信

# ref属性放在普通标签上  例:<input type="text" ref="myinput">
	-通过this.$refs.myinput  拿到的是原生dom对象,通过原生dom修改 标签


#ref属性放在组件上   例:<child ref="mychild"></child>
	-通过this.$refs.mychild  拿到的是组件对象,既然拿到了组件对象,组件对象中的 变量,方法,都能直接通过 . 的方式调用
    -因此不需要关注是子传父,还是父传子,直接通过组件对象,使用即可
ref-父传子
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="vue/vue.js"></script>
</head>
<body>
<div id="app">

    <div>
        <h2>父传子-ref属性</h2>
        <h2>父组件--名字:{{fname}}--年龄:{{fage}}</h2>
        <p><button @click="changeChild">点我更新子组件数据</button></p>
    </div>

        <child ref="mychild"></child>


</div>
</body>
<script>
     var child ={
        template:`
        <div>
        <h2>子组件--名字:{{cname}}--年龄:{{cage}}</h2>
        </div>
        `,
        data(){
            return {
                cname:"刘亦菲",cage:'19'
            }
        },
        methods:{}
    }
    var vm = new Vue({ //根组件
        el:'#app',
        data:{
            fname:'牛牛',fage:'13'
        },
        methods:{
            changeChild(){
                console.log(this.$refs)
                this.$refs.mychild.cname = this.fname
                this.$refs.mychild.cage = this.fage
            }
        },
        components:{  //子组件 通过变量命名赋值给child
            child
        }
    })
</script>
</html>

image

ref-子传父
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="vue/vue.js"></script>
</head>
<body>
<div id="app">

    <div>
        <h2>子传父-ref属性</h2>
        <h2>父组件--名字:{{fname}}--年龄:{{fage}}</h2>
        <p><button @click="changeChild">点我更新子组件数据</button></p>
    </div>

        <child ref="mychild"></child>


</div>
</body>
<script>
     var child ={
        template:`
        <div>
        <h2>子组件--名字:{{cname}}--年龄:{{cage}}</h2>
        </div>
        `,
        data(){
            return {
                cname:"刘亦菲",cage:'19'
            }
        },
        methods:{}
    }
    var vm = new Vue({ //根组件
        el:'#app',
        data:{
            fname:'牛牛',fage:'13'
        },
        methods:{
            changeChild(){
                console.log(this.$refs)
                this.fname = this.$refs.mychild.cname
                this.fage = this.$refs.mychild.cage
            }
        },
        components:{  //子组件 通过变量命名赋值给child
            child
        }
    })
</script>
</html>

动态组件

1.不使用动态组件

组件不能用驼峰体!!!!!!!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>

<div id="app">

    <span @click="handleClick('home')">首页</span>|
    <span @click="handleClick('orderform')">订单</span> |
    <span @click="handleClick('goods')">商品</span>
    
    <home v-if="chooseType=='home'"></home>
    <orderform v-else-if="chooseType=='orderform'"></orderform>
    <goods v-else></goods>

</div>
</body>
<script>
    var goods = {
        template: `
          <div>
              <span>商品页</span>
          </div>
        `
    }
    var home = {
        template: `
          <div>
              <span>首页</span>
          </div>
        `
    }
    var orderform = {
        template: `
          <div>
              <span>订单页</span>
          </div>
        `
    }


    var vm = new Vue({
        el: '#app',
        data: {
            chooseType: 'home'
        },
        methods: {
            handleClick(some) {
                console.log(some)
                console.log(this.chooseType)
                this.chooseType = some
            }
        },
        components: {
            home, goods, orderform
        }
    })
</script>
</html>

不适用动态组件,需要多写几步,我们推荐使用动态组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>

<div id="app">

    <span @click="handleClick('home')">首页</span>|
    <span @click="handleClick('orderform')">订单</span> |
    <span @click="handleClick('goods')">商品</span>

    <component :is="chooseType"></component>

</div>
</body>
<script>
    var goods = {
        template: `
          <div>
              <span>商品页</span>
          </div>
        `
    }
    var home = {
        template: `
          <div>
              <span>首页</span>
          </div>
        `
    }
    var orderform = {
        template: `
          <div>
              <span>订单页</span>
          </div>
        `
    }


    var vm = new Vue({
        el: '#app',
        data: {
            chooseType: 'home'
        },
        methods: {
            handleClick(some) {
                this.chooseType = some
            }
        },
        components: {
            home, goods, orderform
        }
    })
</script>
</html>

keep-alive保持组件不销毁

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>

<div id="app">

    <span @click="handleClick('home')">首页</span>|
    <span @click="handleClick('orderform')">订单</span> |
    <span @click="handleClick('goods')">商品</span>
    <keep-alive>
    <component :is="chooseType"></component>
    </keep-alive>
</div>
</body>
<script>
    var goods = {
        template: `
          <div>
              <span>商品页</span>
              <input type="text">
          </div>
        `
    }
    var home = {
        template: `
          <div>
              <span>首页</span>
              <input type="text">
          </div>
        `
    }
    var orderform = {
        template: `
          <div>
              <span>订单页</span>
              <input type="text">
          </div>
        `
    }


    var vm = new Vue({
        el: '#app',
        data: {
            chooseType: 'home'
        },
        methods: {
            handleClick(some) {
                this.chooseType = some
            }
        },
        components: {
            home, goods, orderform
        }
    })
</script>
</html>

image

插槽

	一般情况下,编写完一个组件之后,组件的内容都是写死的,
	如果我们需要添加数据 只能去组件中修改,拓展性很差
	插槽的概念:
		我们只需要在组件中添加 <slot></slot> 标签,即可在 body的组件标签中添加内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>
<div class="app">

    <hr>
    <home>

        <div>
            <img src="11.jpg" alt="">
        </div>

    </home>
    <hr>

</div>

</body>
<script>

    var home = {
        template: `
          <div>
          <h1>home页面</h1>
            <slot></slot>
            <h1>结束了</h1>
          </div>`,

    }
    var vm = new Vue({
        el: '.app',
        data: {},
        components: {
            home,
        }


    })
</script>
</html>

image

具名插槽
我们在组件的slot 标签属性中添加 name="xx"
xx就是slot的名字, 在body中我们就可以指定slot来编写内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>
<div class="app">

    <hr>
    <home>

        <div slot="start">
            <img src="11.jpg" alt="">
        </div>

         <p slot="end">五菱宏光刹不住,我是有田你记住</p>
    </home>
    <hr>

</div>

</body>
<script>

    var home = {
        template: `
          <div>
          <h1>home页面</h1>
            <slot name="start"></slot>
            <h1>结束了</h1>
            <slot name="end"></slot>
          </div>`,

    }
    var vm = new Vue({
        el: '.app',
        data: {},
        components: {
            home,
        }


    })
</script>
</html>

计算属性

计算属性只有使用的变量发生变化时,才重新运算
计算属性与python中的property伪装很像,可以将方法伪装成属性
计算属性基本使用

输入框输入英文首字母大写案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>
        编写单词,首字母转换成大写展示
    </h1>
    <input type="text" v-model="mytext">
    --{{getUp(mytext)}}
</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            mytext: ''
        },
        methods: {
            getUp(mytext) {
                console.log(mytext)
                return (mytext.slice(0, 1).toUpperCase() + mytext.slice(1))
            }
        }
    })
</script>
</html>

image

使用计算属性

过滤案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.js"></script>
</head>
<body>

<div id="app">

<h1>过滤案例</h1>
    <p>请输入想要搜索的内容 <input type="text" v-model="mytext" ></p>
<p>
  <ul>
        <li v-for="item in newDataList">{{item}}</li>
    </ul>
</p>

</div>

</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            mytext:'',
            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf']
        },
        methods:{
        },
        computed:{
                newDataList(){
                    return this.dataList.filter(item=>item.indexOf(this.mytext)>=0)
                }
        }
    })

</script>
</html>

监听属性

在data中定义了一些变量,只要变量发生变化,我们就执行一个函数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div>
    <div class="app">
        <!--        <span @click="handleClick(1)">Python</span>|    <span @click="handleClick(2)">Linux</span>-->
        <span @click="course_type=1">Python</span>| <span @click="course_type=2">Linux</span>
        <div>
            假设有很多课程,点击上面的标签可以完成过滤
        </div>

    </div>

</div>
</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            course_type: '0'
        },
        created() {
            this.getData()
        },
        methods: {
            getData() {
                // 发送ajax ,获取所有课程,通过course过滤
                // http://127.0.0.1:8080/api/v1/courses?course_type=0
            },
            // handleClick(type){
            //     this.course_type=type
            //     this.getData()
            // }
        },
        watch: {
            course_type() {
                console.log('我变化了')
                this.getData()
            }
        }

    })


</script>
</html>