Vue快速了解并上手-4

系列文章目录

上期我们讲解了v-model等等的一些指令,这期我们来讲解组件方面的内容



1、组件

重复的页面结构,数据,逻辑 都可以抽提成一个组件

  • 特点 简单 高效 不重复
  • 组件和实例相似之处: data/methods/computed/watch 等一应俱全
    注意:
  • data和Vue实例的区别为
  • 组件中data为一个函数且需要返回一个对象
  • 组件没有el选项
  • template 代表其 页面结构 (有且只要一个根元素)

每个组件都是 独立 的 运行作用域、数据、逻辑没有任何关联

1.1、全局组件

全局和局部: 注册方式不同 应用范围不同

注意: 注意命名规范
路径: 实现一个全局组件

  1. 定义一个全局组件
  2. 写入组件选项
  3. 使用组件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
<div id="app" v-cloak>
    <content-a></content-a>
</div>
<script src="./vue.js"></script>
<script>
    Vue.component(
        "content-a",
        {
            template: `
            <div>
                <button @click="add"></button>
                <span>{{count}}</span>
                <button @click="cut"></button>
            </div>
                `,
            data(){
                return{
                    count: 1
                }
            },
            methods: {
                add(){
                    this.count++
                },
                cut(){
                    this.count--
                }
            }
        }
    )
    let vm = new Vue({
        el: '#app',
        data: {
            msg:'ok,ok',
        },
        component:{

        },
        methods: {
            fn(e) {
            //msg=最新的value
                this.msg = e.target.value
            }

        },
        filters:{
            filter01:function (vl) {
                return vl+'filter01'
            },
            filter02:function (vl) {
                return vl+'filter02'
            },
            capita : function (value) {
                return value.charAt(0).toUpperCase() + value.slice(1)
            }
        },
        directives: {
            "focus": {
                inserted(dom) {
                    dom.focus();
                }
            }
        }
    })
</script>
</body>

</html>

上述代码时实现对count的自加自减,也是对全局过滤器的演示

1.2、局部组件

局部组件的实现

  1. 在实例选项compoents中定义局部组件名字
  2. 在组件名字相对应的对象中定义选项(template、data()、…)
  3. 在实例视图中使用组件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
<div id="app" v-cloak>
    <content-a></content-a>
    <content-b></content-b>
</div>
<script src="./vue.js"></script>
<script>
    Vue.component(
        "content-a",
        {
            template: `
            <div>
                <button @click="add"></button>
                <span>{{count}}</span>
                <button @click="cut"></button>
            </div>
                `,
            data(){
                return{
                    count: 1
                }
            },
            methods: {
                add(){
                    this.count++
                },
                cut(){
                    this.count--
                }
            }
        }
    )
    let vm = new Vue({
        el: '#app',
        data: {
            msg:'ok,ok',
        },
        components:{
            'content-b':{
                template: `
            <div>
                <button @click="add"></button>
                <span>{{count}}</span>
                <button @click="cut"></button>
            </div>
                `,
                data(){
                    return{
                        count: 1
                    }
                },
                methods: {
                    add(){
                        this.count++
                    },
                    cut(){
                        this.count--
                    }
                }
            }
        },
        methods: {
            fn(e) {
            //msg=最新的value
                this.msg = e.target.value
            }

        },
        filters:{
            filter01:function (vl) {
                return vl+'filter01'
            },
            filter02:function (vl) {
                return vl+'filter02'
            },
            capita : function (value) {
                return value.charAt(0).toUpperCase() + value.slice(1)
            }
        },
        directives: {
            "focus": {
                inserted(dom) {
                    dom.focus();
                }
            }
        }
    })
</script>
</body>

</html>

1.3、组件的嵌套

  1. 全局组件 嵌套 全局组件
  2. 局部组件 嵌套 全局组件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
<div id="app" v-cloak>
    <content-c></content-c>
</div>
<script src="./vue.js"></script>
<script>
    Vue.component(
        "content-a",
        {
            template: `
            <div>
                <button @click="add"></button>
                <span>{{count}}</span>
                <button @click="cut"></button>
            </div>
                `,
            data(){
                return{
                    count: 1
                }
            },
            methods: {
                add(){
                    this.count++
                },
                cut(){
                    this.count--
                }
            }
        }
    )
    let vm = new Vue({
        el: '#app',
        data: {
            msg:'ok,ok',
        },
        components:{
            'content-b':{
                template: `
            <div>
                <button @click="add"></button>
                <span>{{count}}</span>
                <button @click="cut"></button>
            </div>
                `,
                data(){
                    return{
                        count: 1
                    }
                },
                methods: {
                    add(){
                        this.count++
                    },
                    cut(){
                        this.count--
                    }
                }
            },
            'content-c':{
                template: `
                    <content-a></content-a>
                `,
                data(){
                    return{
                        count: 1
                    }
                },
                methods: {
                    add(){
                        this.count++
                    },
                    cut(){
                        this.count--
                    }
                }
            }
        },
        methods: {
            fn(e) {
            //msg=最新的value
                this.msg = e.target.value
            }

        },
        filters:{
            filter01:function (vl) {
                return vl+'filter01'
            },
            filter02:function (vl) {
                return vl+'filter02'
            },
            capita : function (value) {
                return value.charAt(0).toUpperCase() + value.slice(1)
            }
        },
        directives: {
            "focus": {
                inserted(dom) {
                    dom.focus();
                }
            }
        }
    })
</script>
</body>

</html>

1.4、组件间的通信

组件嵌套 => 父子组件 => 父组件传递数据给子组件使用 => 组件之间的传值 => 也叫组件之间的通信

组件之间的通信根据关系的可以分为:

  1. 父子组件通信
    父组件到子组件
    子组件到父组件
  2. 兄弟组件通信
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
<div id="app">
    <!-- 子组件 -->
    <child-a :msg="msgP"></child-a>
</div>
<script src="./vue.js"></script>
<script>
    Vue.component('child-a', {
        template: `
          <div>
          我是子组件{{count}}
          {{msg}}
          </div>
        `,
        data() {
            return {
                count: 100
            }
        },
        props: ['msg']
    })
    let vm = new Vue({
        el: '#app',
        data: {
            msgP: '我是父组件'
        }
    })
</script>
</body>

</html>

2、路由

组件和模块的区别

  • 模块:侧重于功能或者数据的封装
  • 组件:包含了 template、style 和 script,而它的 script 可以由各种模块组成

单页应用(简称SPA)

  • 传统模式 每个页面及其内容都需要从服务器一次次请求 如果网络差, 体验则会感觉很慢
  • SPA模式, 第一次 加载 会将所有的资源都请求到页面 模块之间切换 不会再请求服务器

SPA优点:

  • 用户体验好,因为前端操作几乎感受不到网络的延迟
  • 完全组件化开发 ,由于只有一个页面,所以原来属于一个个页面的工作被归类为一个个 组件

SPA缺点:

  • 首屏 加载慢(可以只加载所需部分)
  • 不利于 SEO ( 服务端渲染 可以解决)
  • 开发难度高 (框架)

单页应用 SPA-实现原理

  • 可以通过页面地址的锚链接来实现spa
  • hash(锚链接)位于链接地址 # 之后
  • hash值的改变 不会触发 页面刷新
  • hash值是url地址的一部分,会存储在页面地址上 我们可以获取到
  • 可以通过 事件监听 hash值得改变
  • 拿到了hash值,就可以根据不同的hash值进行不同的 内容切换

2.1、基于js路由的实现

通过上一个小节内容可以得出 采用 hash值改变 的特性来进行前端路由切换

  1. 实现导航结构(’#/aaa’)
  2. onhashchange事件监听hash值的改变
  3. 获取hash值 根据值的不同 改变视图内容
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <ul>
        <li><a href="#/aaa">aaa</a></li>
        <li><a href="#/bbb">bbb</a></li>
        <li><a href="#/ccc">ccc</a></li>
        <li><a href="#/ddd">ddd</a></li>
    </ul>
    <!-- 容器 -->
    <div id="main"></div>
    <script>
        //  根据不同内容渲染不同的标识
        let oBox = document.getElementById('main')
        window.onhashchange = function () {
            // 获取hash值
            let hash = location.hash
            console.log(hash)
            hash = hash.replace('#/', '')
            switch (hash) {
                case "aaa":
                    oBox.innerText = 'AAA'
                    break
                case "bbb":
                    oBox.innerText = 'BBB'
                    break
                case "ccc":
                    oBox.innerText = 'CCC'
                    break
                case "ddd":
                    oBox.innerText = 'DDD'
                    break
                default:
                    break
            }
        }
    </script>
</body>

</html>

2.2、vue-router实现

  • Vue-Router 是 Vue.js 官方的路由管理器。
  • 它和 Vue.js 的核心深度集成,让构建单页面应用变得简单
  • 实现根据不同的请求地址 而 显示不同的内容
  • 如果要使用 vue开发项目,前端路由功能 必须使用 vue-router来实现

需要引入js文件:

  • 可以npm
  • cdn
  • 也可以直接下载导入

基本语法:

  1. 导入vue和vue-router
  2. 设置HTML中的内容
  3. 实例化路由对象,配置路由规则
  4. 创建路由对应的组件
  5. 把router实例挂载到vue实例上
2.设置HTML中的内容
<!-- router-link 最终会被渲染成a标签,to指定路由的跳转地址 -->
<router-link to="/users">用户管理</router-link>
<router-link to="/home">首页展示</router-link>
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
// 3.配置路由规则
var router = new VueRouter({
routes: [
{ path: '/users', component: Users }
{ path: '/home', component: Home }
]
});
// 4.创建组件
let Home = {
template: '<div>这是Home内容</div>'
};
let Users = {
template: '<div>这是用户管理内容</div>'
};
// 5.把router实例挂载到vue实例上
var vm = new Vue({
el: '#app',
router
});

2.3、代码实现vue-router

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <!-- 配置路径 -->
        <router-link to="/home">主页</router-link>
        <router-link to="/top">热点</router-link>
        <router-link to="/abouts">关于我们</router-link>
        <!-- 显示的内容 -->
        <router-view></router-view>
    </div>
    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
    <script>
        // 模板内容
        let Home = {
            template: `<div><span>主页</span></div>`
        }
        let Top = {
            template: `<div><span>热点</span></div>`
        }
        let Abouts = {
            template: `<div><span>关于我们</span></div>`
        }
        // 匹配规则
        let router = new VueRouter({
            routes: [{
                path: '/home',
                component: Home
            }, {
                path: '/top',
                component: Top
            }, {
                path: '/abouts',
                component: Abouts
            }]
        })
        let vm = new Vue({
            el: '#app',
            data: {},
            router
        })
    </script>
</body>

</html>

2.4、实现动态路由

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
</head>
<body>
<div id="dianshi">
    <router-link to="/item/8">看什么看这是我的小米电视</router-link>
    <router-link to="/item/9">看什么看这是我的华为电视</router-link>
    <router-view></router-view>
</div>
<script>
    let home = {
        template: `<div>我是home{{$route.params.id}}</div>`,
    }
    let router = new VueRouter({
        routes: [{
            path: '/item/:id',
            component: home
        }]
    })
    let vue = new Vue({
        el: '#dianshi',
        data: {
            msg: 'hello'
        },
        router
    })
</script>
</body>
</html>

2.5、to属性

to有很多赋值方式

<!-- 常规跳转 -->
<!-- <router-link to="/aaa">aaa</router-link> -->
<!-- 变量 -->
<!-- <router-link :to="bbb">bbb</router-link> -->
<!-- 根据对象name跳转 --> (注意:name值是字符串)
<!-- <router-link :to="{name:'ccc'}">ccc</router-link> -->
<!-- 根据对象path跳转 -->(注意:必须得加上/ 不然容易错乱)
<!-- <router-link :to="{path:'/ddd'}">ddd</router-link> -->
<!-- 带参数的跳转 --> (注意获取参数route 不要写成router)
<!--<router-link :to="{name:'eee',params:{id:1}}">体育</router-link> -->
<router-view></router-view>

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <!-- 配置路径 -->
        <router-link to="/home">主页</router-link>
        <router-link :to="top">热点</router-link>
        <router-link :to="{path:'/abouts'}">关于我们</router-link>
        <router-link :to="{name:'aaa'}">AAA</router-link>
        <router-link :to="{name:'bbb',params:{id:300}}">BBB</router-link>

        <!-- 显示的内容 -->
        <router-view></router-view>
    </div>
    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
    <script>
        // 模板内容
        let Home = {
            template: `<div><span>主页</span></div>`
        }
        let Top = {
            template: `<div><span>热点</span></div>`
        }
        let Abouts = {
            template: `<div><span>关于我们</span></div>`
        }
        let AAA = {
            template: `<div><span>AAA</span></div>`
        }
        let BBB = {
            template: `<div><span>BBB{{$route.params.id}}</span></div>`
        }
        // 匹配规则
        let router = new VueRouter({
            routes: [{
                path: '/home',
                component: Home
            }, {
                path: '/top',
                component: Top
            }, {
                path: '/abouts',
                component: Abouts
            }, {
                name: 'aaa',
                path: '/aaa',
                component: AAA
            }, {
                name: 'bbb',
                path: '/bbb/:id',
                component: BBB
            }]
        })
        let vm = new Vue({
            el: '#app',
            data: {
                top: '/top'
            },
            router
        })
    </script>
</body>

</html>

3、重定向

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
<div id="app">
    <!-- 配置路径 -->
    <router-link to="/home">主页</router-link>
    <router-link to="/top">热点</router-link>
    <router-link to="/abouts">关于我们</router-link>
    <!-- 显示的内容 -->
    <router-view></router-view>
</div>
<script src="./vue.js"></script>
<script src="./vue-router.js"></script>
<script>
    // 模板内容
    let Home = {
        template: `<div><span>主页</span></div>`
    }
    let Top = {
        template: `<div><span>热点</span></div>`
    }
    let Abouts = {
        template: `<div><span>关于我们</span></div>`
    }
    // 匹配规则
    let router = new VueRouter({
        routes: [{
            path: '/home',
            component: Home
        }, {
            path: '/top',
            component: Top,
            redirect:'/home'
        }, {
            path: '/abouts',
            component: Abouts
        }]
    })
    let vm = new Vue({
        el: '#app',
        data: {},
        router
    })
</script>
</body>

</html>

4、编程式导航

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
<div id="app">
    <!-- 配置路径 -->
    <router-link to="/home">主页</router-link>
    <router-link :to="top">热点</router-link>
    <router-link :to="{path:'/abouts'}">关于我们</router-link>
    <router-link :to="{name:'aaa'}">AAA</router-link>
    <router-link :to="{name:'bbb',params:{id:300}}">BBB</router-link>
    <button @click="fnclick">编程式导航</button>
    <!-- 显示的内容 -->
    <router-view></router-view>
</div>
<script src="./vue.js"></script>
<script src="./vue-router.js"></script>
<script>
    // 模板内容
    let Home = {
        template: `<div><span>主页</span></div>`
    }
    let Top = {
        template: `<div><span>热点</span></div>`
    }
    let Abouts = {
        template: `<div><span>关于我们</span></div>`
    }
    let AAA = {
        template: `<div><span>AAA</span></div>`
    }
    let BBB = {
        template: `<div><span>BBB{{$route.params.id}}</span></div>`
    }
    // 匹配规则
    let router = new VueRouter({
        routes: [{
            path: '/home',
            component: Home
        }, {
            path: '/top',
            component: Top,
            redirect: '/home'
        }, {
            path: '/abouts',
            component: Abouts
        }, {
            name: 'aaa',
            path: '/aaa',
            component: AAA
        }, {
            name: 'bbb',
            path: '/bbb/:id',
            component: BBB
        }]
    })
    let vm = new Vue({
        el: '#app',
        data: {
            top: '/top'
        },
        methods: {
            fnclick() {
                this.$router.push({
                    name: 'aaa'
                })
            }
        },
        router
    })
</script>
</body>

</html>

5、路由激活样式

当前路由在导航中是拥有激活class样式的

<a href="#/bj" class="router-link-exact-active router-link-active">北京</a>

总结

这里我们主要讲了路由、组件等等方面的内容、下一期我们讲解动画方面的知识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值