Vue基础教程深入篇

1. 父级向子级组件传值

父组件中可以使用静态绑定传入子组件的值,也可以动态绑定传入子组件的值:

<!doctype html>
<html lang="zh-CH">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>父级向子级组件传值</title>
</head>
<body>
<div id="app">
    <App></App>
</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    Vue.component('VBtn', {
        data() {
            return {}
        },
        template: `
          <button @click="clickHandler">{{ id }}</button>
        `,
        props: ['id'],
        methods: {
            clickHandler() {
                // 每个组件中的this指的是当前组件对象
                console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
            }
        },
        created() {
            console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
        }
    })
    let Vheader = {
        data() {
            return {
                text: '我是子组件中的数据!'
            }
        },
        template: `
          <div>
          {{ text }}分割线下面是来自父组件传过来的值:
          <hr>
          msg:{{ msg }}<br>
          post.id:{{ post.id }}<br>
          post.title:{{ post.title }}<br><br>
          <VBtn :id="post.id" @click="clickHandler"></VBtn>
          </div>
        `,
        // 挂载父组件属性。只要声明了父组件的属性就可以使用
        props: ['msg', 'post'],
        methods: {
            // 由于是VBtn调用clickHandler,所以这里的clickHandler不会被执行
            clickHandler() {
                alert(1)
            }
        },
        created() {
            console.log(this) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
        }
    }
    let App = {
        data() {
            return {
                text: '我是父组件中准备传入子组件中的数据,可以使用v-bind动态绑定也可以静态绑定!',
                post: {
                    id: 1,
                    title: '我是父组件自定的属性title!'
                }
            }
        },
        template: `
          <div>
          <Vheader :msg="text" :post="post"></Vheader>
          </div>
        `,
        components: {
            Vheader: Vheader
        },
        created() {
            console.log(this) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
        }
    }
    let vm = new Vue({
        el: '#app',
        data() {
            return {}
        },
        components: {
            App
        },
        created() {
            console.log(this) // Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
        }
    })
</script>
</html>

在这里插入图片描述

2. 子级向父级组件传值

这里沿用第1部分做的:

<!doctype html>
<html lang="zh-CH">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>子组件向父组件传值</title>
</head>
<body>
<div id="app">
    <App></App>
</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    Vue.component('VBtn', {
        data() {
            return {}
        },
        template: `
          <button @click="clickHandler">{{ id }}</button>
        `,
        props: ['id'],
        methods: {
            clickHandler() {
                // 每个组件中的this指的是当前组件对象
                console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
                // this.$emit('父组件声明自定义的事件', '传值')
                console.log('VBtn组件:', this.id)
                this.$emit('VheaderHandler', this.id)
            }
        },
        created() {
            console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
        },
    })
    let Vheader = {
        data() {
            return {
                text: '我是子组件中的数据!'
            }
        },
        template: `
          <div>
          {{ text }}分割线下面是来自父组件传过来的值:
          <hr>
          msg:{{ msg }}<br>
          post.id:{{ post.id }}<br>
          post.title:{{ post.title }}<br><br>
          <VBtn :id="post.id" @VheaderHandler="VheaderHandler"></VBtn>
          </div>
        `,
        // 挂载父组件属性。只要声明了父组件的属性就可以使用
        props: ['msg', 'post'],
        methods: {
            // 由于是VBtn调用clickHandler,所以这里的clickHandler不会被执行
            VheaderHandler(val) { // @VheaderHandler与其值可以不一样,但必须与子组件中的this.$emit('VheaderHandler', this.id)中的VheaderHandler一样
                console.log('Vheader组件:' + val)
                this.$emit('AppHandler', val)
            }
        },
        created() {
            console.log(this) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
        }
    }
    let App = {
        data() {
            return {
                text: '我是父组件中准备传入子组件中的数据,我需要通过v-bind绑定才能使用!',
                post: {
                    id: 1,
                    title: '我是父组件自定的属性title!'
                }
            }
        },
        template: `
          <div>
          <Vheader :msg="text" :post="post" @AppHandler="app_handler"></Vheader>
          </div>
        `,
        components: {
            Vheader: Vheader
        },
        created() {
            console.log(this) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
        },
        methods: {
            app_handler(val) {
                console.log('App组件:' + val)
                this.post.id = val
            }
        }
    }
    let vm = new Vue({
        el: '#app',
        data() {
            return {}
        },
        components: {
            App
        },
        created() {
            console.log(this) // Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
        }
    })
</script>
</html>

在这里插入图片描述

3. 平行组件传值
<!doctype html>
<html lang="zn-CH">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>平行组件传值</title>
</head>
<body>
<div id="app">
    <App></App>
</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    // Test1组件向Test2传值,Test2要声明事件:$on('事件的名字',function(){}),Test1要触发事件:$emit('Test声明的事件的名字','值')
    // 前提:这两个方法必须同一个实例化对象“bus”上
    let bus = new Vue() // 新建Vue对象作为两个方法共同绑定的实例化对象
    Vue.component('Test2', {
        data() {
            return {
                txt: '我是Test2组件!',
                text: ''
            }
        },
        template: `
          <div>
          {{ txt }}
          {{ text }}
          </div>
        `,
        created() {
            bus.$on('testData', (val) => {
                console.log(bus)
                console.log('传递过来的值:' + val)
                this.text = val
            })
        }
    })
    Vue.component('Test1', {
        data() {
            return {
                msg: '收到来自Test1组件的数据!'
            }
        },
        props: ['txt'],
        template: `
          <button @click="clickHandler">{{ txt }}</button>
        `,
        methods: {
            clickHandler() {
                console.log("bus:" + bus)
                bus.$emit('testData', this.msg)
            }
        }
    })
    let Vheader = {
        data() {
            return {
                txt: '传递'
            }
        },
        template: `
          <div class="header">
          <Test1 :txt="txt"></Test1>
          <Test2></Test2>
          </div>
        `
    }
    let App = {
        data() {
            return {}
        },
        template: `
          <div class="app">
          <Vheader></Vheader>
          </div>
        `,
        components: {
            Vheader: Vheader
        }
    }
    let vm = new Vue({
        el: '#app',
        data() {
            return {}
        },
        components: {
            App: App
        }
    })
</script>
</html>

在这里插入图片描述
在这里插入图片描述

4. Vue全家桶是什么

vue和vue-router以及vuex三者合起来是Vue的全家桶,Vue全家桶主要用来做SPA(Simple Page Application)单页面应用。

5. 为什么要使用单页面应用

传统的路由跳转,如果后端资源比较多,会导致页面出现 “白屏” 现象。让前端来做路由,在某个生命周期函数中发送 AJAX,数据驱动视图,提升用户体验。

6. 安装vue-cli脚手架

淘宝npm镜像:https://developer.aliyun.com/mirror/NPM?from=tnpm
vue-cli官网:https://cli.vuejs.org/zh/guide/

# 安装cnpm
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
# 安装vue-cli
$ npm install -g @vue/cli
7. 过滤器的使用

局部过滤器:在当前组件内部使用过滤器。使用过滤器其实就是给某系数据“添油加醋”,使用的格式(伪代码):

//声明
filters:{
    '过滤器的名字':function(val,a,b){
        // val就是当前的数据,a和b是参数
	}
}
//使用管道符
数据 | 过滤器的名字('erics''thanlon') // a='erics',b='thanlon',管道符|左右的空格也可以删除

局部过滤器使用示例:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>过滤器</title>
</head>
<body>
<div id="app">
    <App/>
</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/moment.js"></script>
<script>
    // 这是个局部组件,非全局组件
    let App = {
        data() {
            return {
                msg: 'Hello World!',
                time: new Date()
            }
        },
        template: `
          <div>
          {{ msg|myReverse }}
          {{ time | myTime('YYYY-MM-DD') }}
          </div>
        `,
        filters: {
            myReverse: function (val) {
                console.log(val) // Hello World!
                return val.split('').reverse().join('') // 'Hello World!'->['H','e',,,,]->['!','d']->'!dlroW olleH'
            },
            // 年-月-日(YYYY-MM-DD),年可以不区分大小写,但月日必须区分
            myTime: function (val, formatStr) {
                return moment(val).format(formatStr)
            }
        }
    }
    new Vue({
        el: '#app',
        data() {
            return {}
        },
        components: {
            App
        }
    })
</script>
</html>

在这里插入图片描述

全局过滤器:只要过滤器一创建,在任何组件中都能使用。使用的格式(伪代码):

Vue.filter('过滤器的名字'function(val,a,b){})
//在各个组件中都能使用
数据 | 过滤器的名字('thanlon''erics')

全局过滤器使用示例:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>过滤器</title>
</head>
<body>
<div id="app">
    <App/>
</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/moment.js"></script>
<script>
    //全局过滤器,
    Vue.filter('myTime', function (val, formatStr) {
        return moment(val).format(formatStr);
    })
    // 这是个局部组件,非全局组件
    let App = {
        data() {
            return {
                msg: 'Hello World!',
                time: new Date()
            }
        },
        template: `
          <div>
          {{ msg|myReverse }}
          {{ time | myTime('YYYY-MM-DD') }}
          </div>
        `,
        filters: {
            myReverse: function (val) {
                console.log(val) // Hello World!
                return val.split('').reverse().join('') // 'Hello World!'->['H','e',,,,]->['!','d']->'!dlroW olleH'
            },
        }
    }
    new Vue({
        el: '#app',
        data() {
            return {}
        },
        components: {
            App
        }
    })
</script>
</html>

同样的效果:
在这里插入图片描述

过滤器是针对某一个页面的某些个操作,如将后端返回的钱数加上美元符号$或者做其它的处理,如将后端返回的很长的文本进行处理,截取指定长度的字符串,多余的字符串可以拼接上三个点。

8. 生命周期的钩子函数

开始到结束的过程就是一个生命周期,Vue生命周期的钩子函数主要有以下几种:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、activated、deactivated、beforeDestory、destoryed。

beforeCreate:组件创建之前
created:组件创建之后
beforeMount:装载数据到DOM之前
mounted:装载数据到DOM之后
beforeUpdate:获取原始DOM
updated:获取更新之后的DOM
activated:激活当前组件(vue提供内置组件 <keep-alive></keep-alive>
deactivated:停用当前组件
beforeDestory:组件销毁之前
destoryed:组件销毁之后

生命周期钩子函数.html:(不建议使用中文命名)

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>生命周期钩子函数</title>
</head>
<body>
<div id="app">
    <App></App>
</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let Test = {
        data() {
            return {
                msg: 'Erics',
                count: 0,
                timer: null,
            }
        },
        template: `
          <div id="test">
          <span id="box">我的名字是{{ msg }}!</span>
          <hr>
          <button @click="changeName">修改</button>
          <hr>
          {{ count }}
          </div>
        `,
        methods: {
            changeName() {
                this.msg = 'Kiku'
                document.getElementById('box').style.color = 'red'
            }
        },
        beforeCreate() {
            /**
             * 组件创建之前
             * beforeCreate获取不到数据
             */
            console.log('组件创建之前:', this.msg)
        },
        created() {
            /**
             * 组件创建之后,使用该组件就会触发以上钩子方法,created中可以操作数据、可以发送AJAX,并且可以实现数据驱动视图
             * 已经有数据了(DOM渲染完成之前),created只是把template创建出来,但是还没有被渲染到app组件中,更没有渲染到Vue中
             * Tip:90%的情况下是在created方法中获取数据
             * 组件创建之后才可以获取数据
             */

            console.log('组件创建之后:', this.msg)
            // this.msg = 'Thanlon'
            this.timer = setInterval(() => {
                this.count++
            }, 5000)
            /**
             *虚拟DOM:由React引出,比原生js和jquery操作DOM效率要有所提高
             */
        },
        beforeMount() {
            /**
             * 装载数据到DOM之前会调用
             */
            console.log('装载数据到DOM之前会调用:', document.getElementById('app'))
        },
        mounted() {
            /**
             * 这个地方可以操作DOM,装载数据到DOM之后(DOM挂载完成)会被调用,可以获取真实存在的DOM元素(标签已经被渲染了)
             * Tip:这里可以操作DOM;能用数据驱动改数据就不用操作DOM
             */
            console.log('装载数据到DOM之后会调用:', document.getElementById('app'))
        },
        beforeUpdate() {
            /**
             * 在更新之前调用,获取原始的DOM
             */
            console.log('在更新之前调用:')
            console.log(document.getElementById('app').innerHTML);
        },
        updated() {
            /**
             * 在更新之后调用,获取嘴型的DOM
             */
            console.log('在更新之后调用:')
            console.log(document.getElementById('app').innerHTML)
        },
        beforeDestroy() {
            console.log('销毁组件之前调用!')
        },
        destroyed() {
            console.log('销毁组件之后调用!', this.timer) // 每次创建定时器数字是不一样的
            // 销毁定时器,销毁和创建很消耗性能
            clearInterval(this.timer)
        },
        activated() {
            console.log('组件被激活了!')
        },
        deactivated() {
            console.log('组件被停用了!')
        }
    }
    let App = {
        data() {
            return {
                isShow: true
            }
        },
        /**
         template: `
         <div>
         <Test v-if="isShow"></Test>
         <hr>
         <button @click="clickHandler">改变Test组件的生死!</button>
         </div>
         `,
         **/
        // 这个组件被缓存起来,keep-alive是Vue内置的,其作用是让组件产生缓存
        template: `
          <div>
          <keep-alive>
            <Test v-if="isShow"></Test>
          </keep-alive>
          <hr>
          <button @click="clickHandler">改变Test组件的生死!</button>
          </div>
        `,
        components: {
            Test: Test
        },
        methods: {
            clickHandler() {
                this.isShow = !this.isShow
            }
        }

    }
    let vm = new Vue({
        el: '#app',
        data() {
            return {};
        },
        components: {
            App: App
        }
    })
</script>
</html>

没有使用 keep-alive 缓存组件:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
使用 keep-alive 缓存组件时:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

created 和 mounted 是比较重要的两个钩子函数!created 是在组件创建完成后触发的钩子函数,在函数中可以发起 ajax (XMLHttpRequest,XHR)、axios、fetch、$ajax 请求实现数据驱动视图。mounted 是在 DOM 装载数据之后调用,可以在这里请求数据。组件创建完成后和 DOM 装载数据之后发送获取数据的请求都是没所谓的。获取数据的过程是很快的,大部分是在组件加载之后提前准备好数据。

9. router的基本使用

router的基本使用.html:

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>router的基本使用</title>
</head>
<body>
<div id="app">

</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    let Home = {
        data() {
            return {}
        },
        template: `
          <div>首页内容!</div>
        `
    }
    let Course = {
        data() {
            return {}
        },
        template: `
          <div>免费课程内容!</div>
        `
    }
    const router = new VueRouter({
        mode: 'history',
        //定义路由规则
        routes: [
            {
                path: '/',
                redirect: '/home'
            },
            {
                path: '/home',
                component: Home
            },
            {
                path: '/course',
                component: Course
            }
        ]
    })
    let App = {
        data() {
            return {}
        },
        // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
        template: `
          <div>
          <div class="header">
            <router-link to="/">首页</router-link>
            <router-link to="/course">免费课程</router-link>
          </div>
          <hr>
          <router-view></router-view>
          </div>
        `,
        components: {
            Home: Home
        }
    }
    let vm = new Vue({
        el: '#app',
        // 挂载路由对象(router对象)到Vue的实例中
        router: router,
        data() {
            return {}
        },
        template: `
          <App></App>
        `,
        components: {
            App: App
        }
    })

</script>
</html>

在这里插入图片描述
在这里插入图片描述

router-link默认被渲染成a标签,to属性会被渲染成href!

10. 命名路由和动态路由匹配

命名路由其实就是给路由命名,使用的时候直接使用路由的名字来代替路由。

命名路由.html:

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>命名路由</title>
</head>
<body>
<div id="app">

</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    let Home = {
        data() {
            return {}
        },
        template: `
          <div>首页内容!</div>
        `
    }
    let Course = {
        data() {
            return {}
        },
        template: `
          <div>免费课程内容!</div>
        `
    }
    const router = new VueRouter({
        mode: 'history',
        //定义路由规则
        routes: [
            {
                path: '/',
                redirect: '/home'
            },
            {
                path: '/home',
                name: 'Home',
                component: Home
            },
            {
                path: '/course',
                name: 'Course',
                component: Course
            }
        ]
    })
    let App = {
        data() {
            return {}
        },
        // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
        template: `
          <div>
          <div class="header">
            <router-link :to="{name:'Home'}">首页</router-link>
            <router-link :to="{name:'Course'}">免费课程</router-link>
          </div>
          <hr>
          <router-view></router-view>
          </div>
        `,
        components: {
            Home: Home
        }
    }
    let vm = new Vue({
        el: '#app',
        // 挂载路由对象
        router: router,
        data() {
            return {}
        },
        template: `
          <App></App>
        `,
        components: {
            App: App
        }
    })
</script>
</html>

/user/1和/user/2加载的是同一个组件,动态路由匹配示例:

动态路由匹配.html:

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>动态路由匹配</title>
</head>
<body>
<div id="app">

</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    let User = {
        data() {
            return {
                user_id: null,
            }
        },
        template: `
          <div>我是用户{{ user_id }}!</div>
        `,
        created() {
            /**
             * 当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
             * 只调用一次
             */
            console.log(this.$route) // 路由信息对象:{name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
        },
        watch: {
            '$route'(to, from) {
                // 对路由变化做出响应
                console.log('to:', to) // to: {name: "User", meta: {…}, path: "/user/2", hash: "", query: {…}, …}\
                console.log('from:', from) // from: {name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
                console.log(to.params.id)
                this.user_id = to.params.id
                // 发送AJAX
            }
        }
    }
    // 创建路由
    const router = new VueRouter({
        mode: 'history',
        //定义路由规则
        routes: [
            {
                path: '/user/:id',
                name: 'User',
                component: User
            },
        ]
    })
    let App = {
        data() {
            return {}
        },
        // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
        template: `
          <div>
          <div class="header">
            <router-link :to="{name:'User',params:{id:1}}">用户1</router-link>
            <router-link :to="{name:'User',params:{id:2}}">用户2</router-link>
          </div>
          <hr>
          <router-view></router-view>
          </div>
        `,
        components: {
            User: User
        }
    }
    let vm = new Vue({
        el: '#app',
        // 挂载路由对象
        router: router,
        data() {
            return {}
        },
        template: `
          <App></App>
        `,
        components: {
            App: App
        }
    })
</script>
</html>

在这里插入图片描述

watch可以用来监听路由的变化!

$.route是路由信息对象,$router是路由对象VueRouter!

11. 编程式导航

上面所有部分使用的是声明式导航:

<router-link :to="{name:'User',params:{id:1}}">用户1</router-link>
<router-link :to="{name:'User',params:{id:2}}">用户2</router-link>

编程式导航:

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>编程式导航</title>
</head>
<body>
<div id="app">

</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    let Home = {
        data() {
            return {}
        },
        template: `
          <div>我是首页</div>
        `
    }
    let User = {
        data() {
            return {
                user_id: null,
            }
        },
        template: `
          <div>
          <button @click="clickHandler">跳转首页</button>
          <span>User{{ user_id }}!</span>
          </div>
        `,
        created() {
            /**
             * 当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
             * 只调用一次
             */
            console.log(this.$route) // 路由信息对象:{name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
        },
        watch: {
            '$route'(to, from) {
                // 对路由变化做出响应
                console.log('to:', to) // to: {name: "User", meta: {…}, path: "/user/2", hash: "", query: {…}, …}\
                console.log('from:', from) // from: {name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
                console.log(to.params.id)
                this.user_id = to.params.id
                // 发送AJAX
            }
        },
        methods: {
            // 编程式导航
            clickHandler() {
                this.$router.push({
                    name: 'Home'
                })
            }
        }
    }
    // 创建路由
    const router = new VueRouter({
        mode: 'history',
        //定义路由规则
        routes: [
            {
                path: '/home',
                name: 'Home',
                component: Home
            },
            {
                path: '/user/:id',
                name: 'User',
                component: User
            },
        ]
    })
    let App = {
        data() {
            return {}
        },
        // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
        template: `
          <div>
          <div class="header">
            <router-link :to="{name:'User',params:{id:1}}">用户1</router-link>
            <router-link :to="{name:'User',params:{id:2}}">用户2</router-link>
          </div>
          <hr>
          <router-view></router-view>
          </div>
        `,
        components: {
            User: User
        }
    }
    let vm = new Vue({
        el: '#app',
        // 挂载路由对象
        router: router,
        data() {
            return {}
        },
        template: `
          <App></App>
        `,
        components: {
            App: App
        }
    })
</script>
</html>

在这里插入图片描述
在这里插入图片描述

12. refs属性的使用

refs属性可以用来获取标签原生的DOM对象和组件实例,需要在mounted函数中获取。

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>refs属性的使用</title>
</head>
<body>
<div id="app">

</div>
</body>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    Vue.component('Test', {
        data() {
            return {}
        },
        template: `
          <div>我是测试组件1!</div>
        `
    })
    Vue.component('Test2', {
        data() {
            return {}
        },
        template: `
          <div>我是测试组件2!</div>
        `
    })
    let App = {
        data() {
            return {}
        },
        template: `
          <div>
          <input type="text" ref="input">
          <Test ref="abc"></Test>
          <Test2 ref="def"></Test2>
          </div>
        `,
        mounted() {
            console.log(this.$refs.input) // 获取原始DOM对象:<input type="text">
            console.log(this.$refs) // {input: input}...可以展开
            this.$refs.input.focus()
            console.log(this) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
            console.log(this.$root) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
            console.log(this.$refs.abc) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
            console.log(this.$refs.parent) // undefined
            console.log(this.$refs.root) // undefined
            console.log(this.$children[0]) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
        }
    }
    let vm = new Vue({
        el: '#app',
        data() {
            return {}
        },
        template: `
          <App></App>
        `,
        components: {
            App
        }
    })
</script>
</html>

在这里插入图片描述

13. 模块化初探索

使用node来运行模块化的JavaScript程序:

test.js:

let person = {
    name: 'erics'
}
module.exports = person

index.js:

let person = require('./test')
console.log(person)
console.log(person.name)

可以使用 node index.js 命令来运行,

$ node index.js 
{ name: 'erics' }
erics

使用webpack打包:

module.js:

let person = {
    name: 'erics',
    func: function () {
        alert('success!')
    }
}
export default person;

main.js:

import person from './module'
console.log(person.func())

使用webpack进行打包:

$ sudo webpack ./main.js -o ./bundle.js
Hash: b7b9dbe6291ed213470d
Version: webpack 4.44.1
Time: 168ms
Built at: 2020/08/21 下午1:52:26
    Asset   Size  Chunks             Chunk Names
bundle.js  1 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[0] ./main.js + 1 modules 170 bytes {0} [built]
    | ./main.js 56 bytes [built]
    | ./module.js 114 bytes [built]

打包完成后当前目录中多了一个bundle.js文件,这就是打包后的文件。在index.html中只需要引入它:

index.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

</body>
<script src="bundle.js"></script>
</html>

main.js和module.js里面的代码成功被执行:
在这里插入图片描述
可以抛出多个变量,修改model.js和main.js重新打包,

module.js:

let person = {
    name: 'erics',
    func: function () {
        alert('success!')
    }
}
let name = 23
// 可以抛出多个变量
export {name}
export let nowYear = 2020
export default person;

main.js:

import * as a from './module'

console.log(a)

在这里插入图片描述
当然可以使用a.xxx来执行函数或者获取变量。

webpack依赖于node.js!

14. Vue的模块化初探索

可以把模块化应用在Vue上,

App.js:

let App = {
    template: `
    <div>我是App组件!</div>
    `
}
export default App;

main.js:

import Vue from './vue'
import App from './App'

let vm = new Vue({
    el: '#app',
    template: `
        <App></App>
    `,
    components: {
        App
    }
})

index.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="./bundle.js"></script>
</html>

使用webpack命令打包:webpack main.js -o bundle.js,然后可以正常访问 index.html

15. webpack的使用

很明显上面的例子中每次更新 JavaScript 代码都会重新打包,这是很繁琐的。实际上,通过设置完全可以自动打包,实时编译。首先需要通过 npm -init --yes 命令来创建配置文件 package.json

{
  "name": "webpack_use",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

接下来通过 $ cnpm i webpack -D 下载 webpack

可以指定webpack的版本:$ cnpm i webpack@3.12.0 -D

下载完成后配置文件 package.json 中发生了变化:

"devDependencies": {
  "webpack": "^4.44.1"
}

devDependencies 指的是开发环境依赖。可以对 package.json 进行修改,使用 npm 命令 $ npm run dev 来替代 $ webpack ./main.js -o ./bundle.js 打包文件。所以,还需要修改配置文件:

"scripts": {
  "dev": "webpack ./main.js ./bundle.js"
},

还可以进行改进,修改 package.json :

"scripts": {
  "dev": "webpack"
},

我们想要只使用 webpack 命令来打包,可以在项目中创建一个 webpack 默认的配置文件 webpack.config.js,该配置文件写的都是 nodejs 代码:

module.exports = {
    entry: {
        'main': './main.js'
    },
    output: {
        'filename': './bundle.js'
    }
}

使用 $npm run dev 会优先找配置文件 webpack.config.js,找到入口 main.js,打包输出 bundle.js。为了实现 监听代码的改动自动编译,需要加上 watch:true

module.exports = {
    entry: {
        'main': './main.js'
    },
    output: {
        'filename': './bundle.js'
    },
    watch: true
}

开发环境中需要有监听代码自动编译功能,生产环境不需要,

webpack.dev.config.js:

module.exports = {
    entry: {
        'main': './main.js'
    },
    output: {
        'filename': './bundle.js'
    },
    watch: true
}

webpack.pro.config.js:

module.exports = {
    entry: {
        'main': './main.js'
    },
    output: {
        'filename': './bundle.js'
    }
}

package.json:

{
  "name": "webpack_use",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "dev": "webpack --config ./webpack.dev.config.js",
    "build": "webpack --config ./webpack.pro.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12"
  }
}

如果是新版本的 webpack,可以这样配置,

webpack.pro.config.js:

module.exports = {
    // entry: './main.js',
    entry: {
        'main': './main.js'
    },
    output: {
        'filename': './bundle.js'
    },
    watch: true,
    mode: 'development'
}

package.json:

{
  "name": "webpack_use",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12"
  }
}
16. webpack中loader的使用

可以把css直接打包到js文件中,不需要再html文件中再引用。新建 index.css 文件,在里面写好样式,然后导入到 main.js 中,

index.css:

body{
    background: rebeccapurple;
}

main.js:

import Vue from './vue'
import App from './App'
import './index.css'
let vm = new Vue({
    el: '#app',
    template: `
        <App></App>
    `,
    components: {
        App
    }
})

但是会报错:

ERROR in ./index.css 1:4
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> body{
|     background: rebeccapurple;
| }
 @ ./main.js 3:0-20

在组件中引入css,需要用到css-loader和style-loader, css-loader是用来解析css文件,style-loader是用来解析style标签的。所以需要下载并配置它们:$ cnpm i css-loader style-loader -D

webpack.config.js:

module.exports = {
    // entry: './main.js',
    entry: {
        'main': './main.js'
    },
    output: {
        'filename': './bundle.js'
    },
    watch: true,
    mode: 'development',
    module: {
        rules: [
            {
                /**
                 * 遇到后缀是css的文件,webpack首先用css-loader加载器去解析这个文件
                 * 最后计算完的css,将会使用style-loader生成一个内容为最终解释完的css代码的style标签,放在head标签里
                 * webpack在打包国城中,遇到后缀为css的文件,就会使用style-loader和css-loader去加载这个文件
                 */
                test: /\.css$/, // 后缀是css的文件
                loader: 'style-loader!css-loader', // 先去使用css-loader解析css文件再使用style-loader生成style标签(link)插入head标签中
            }
        ]
    }
}

这个时候css就会被加入到html中。

17. webpack中plugin的使用

一般也会把 index.html 文件自动生成到 dist 文件中,所以需要使用到 html-webpack-plugin 插件。安装该插件:$ cnpm i html-webpack-plugin -D,指定版本需要加上@跟版本号。另外一个命令是 $ cnpm i html-webpack-plugin --save-dev。还需要在 webpack.config.js 进行配置:

const path = require('path')
// 导入模块
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    // entry: './main.js',
    entry: {
        // 可以有多个入口,也可以有一个,如果有一个默认从这个入口开始分析
        'main': './src/main.js'
    },
    output: {
        // 指定产出目录
        path: path.resolve('./dist'), // 相对转绝对路径,dist也可以改成static,webpack默认使用dist
        'filename': 'build.js'
    },
    watch: true, // 文件监视改动,自动产生build.js
    mode: 'development',
    module: {
        rules: [
            {
                /**
                 * 遇到后缀是css的文件,webpack首先用css-loader加载器去解析这个文件
                 * 最后计算完的css,将会使用style-loader生成一个内容为最终解释完的css代码的style标签,放在head标签里
                 * webpack在打包国城中,遇到后缀为css的文件,就会使用style-loader和css-loader去加载这个文件
                 */
                test: /\.css$/, // 后缀是css的文件
                use: ["style-loader", 'css-loader',], // 先去使用css-loader解析css文件再使用style-loader生成style标签(link)插入head标签中
            }
        ]
    },
    // 添加插件
    plugins: [
        new HtmlWebpackPlugin({
            // 插件的执行运行与元素索引有关
            template: './src/index.html', //参照物
        })
    ]
}

生成之前的项目目录结构:
在这里插入图片描述
执行 $ npm run dev 执行生成之后的目录结构:
在这里插入图片描述

index.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack中plugin的使用</title>
</head>
<body>
<div id="app"></div>
<script src="build.js"></script>
</body>
<!--下面是自己写的,也可以不要-->
<script src="dist/build.js"></script>
</html>
18. 单文件的使用

使用 $ cnpm i vue-loader vue-template-compiler -D 下载用于解析 Vue文件的包 vue-loadervue-template-compiler。创建 App.vue 文件:

<!--组件的模板结构-->
<template>
  <div>
   App组件
  </div>
</template>
<!--组件的业务逻辑-->
<script>
export default {
  name:'App',
  data() {
    return {
      text: 'Hello fingle file...'
    }
  }
}
</script>
<!--组件的样式-->
<style>
body {
  background-color: rebeccapurple;
}
</style>

需要在 webpack.config.js 中进行配置:

const path = require('path')
// 导入模块
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
    // entry: './main.js',
    entry: {
        // 可以有多个入口,也可以有一个,如果有一个默认从这个入口开始分析
        'main': './src/main.js'
    },
    output: {
        // 指定产出目录
        path: path.resolve('./dist'), // 相对转绝对路径,dist也可以改成static,webpack默认使用dist
        'filename': 'build.js'
    },
    watch: true, // 文件监视改动,自动产生build.js
    mode: 'development',
    module: { // 这个节点用于配置所有的第三方模块加载器
        rules: [
            {
                /**
                 * 遇到后缀是css的文件,webpack首先用css-loader加载器去解析这个文件
                 * 最后计算完的css,将会使用style-loader生成一个内容为最终解释完的css代码的style标签,放在head标签里
                 * webpack在打包国城中,遇到后缀为css的文件,就会使用style-loader和css-loader去加载这个文件
                 */
                test: /\.css$/, // 后缀是css的文件
                use: ["style-loader", 'css-loader',], // 先去使用css-loader解析css文件再使用style-loader生成style标签(link)插入head标签中
            },
            {
                test: /\.vue$/,
                use: 'vue-loader'
            }
        ]
    },
    // 添加插件
    plugins: [
        new HtmlWebpackPlugin({
            // 插件的执行运行与元素索引有关
            template: './index.html', //参照物
        }),
        new VueLoaderPlugin()
    ]
}

还要记得修改 main.js:

import Vue from './vue'
import App from './App.vue'
import './index.css'
let vm = new Vue({
    el: '#app',
    template: `<App></App>`,
    components: {
        App
    }
})

执行 $ npm run dev 命令正常打包即可!

19. 单页面SPA应用

使用 $ cnpm i vue vue-router -S 安装 vuevue-router 模块,-S 表示当前项目依赖,查看 package.json:

{
  "name": "webpack_use",
  "version": "1.0.0",
  "description": "",
  "main": "src/main.js",
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^4.2.1",
    "html-webpack-plugin": "^4.3.0",
    "style-loader": "^1.2.1",
    "vue-loader": "^15.9.3",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12"
  },
  "dependencies": {
    "vue": "^2.6.12",
    "vue-router": "^3.4.3"
  }
}

配置路由:main.js

import Vue from './vue'
import App from './App.vue'
import './index.css'
import VueRouter from 'vue-router'
import Home from './components/Home/Home'
import Course from './components/Course/Course'

//创建路由对象
const router = new VueRouter({
    // 配置路由信息
    routers: [
        {
            path: '/',
            name: 'Home',
            component: Home
        },
        {
            path: '/course',
            name: 'Course',
            component: Course
        },
    ]
})
let vm = new Vue({
    el: '#app',
    router: router,
    template: `
      <App></App>`,
    components: {
        App
    }
})

常用配置相关参数:

--open:自动打开浏览器
--hot:热更新,不在刷新的情况下替换css样式
--inline:自动刷新
--port 9000:指定端口
--process:显示编译进度

希望可以在服务器上运行,下载模块:$ cnpm i webpack-dev-server --save-dev,查看 package.json:

{
  "name": "webpack_use",
  "version": "1.0.0",
  "description": "",
  "main": "src/main.js",
  "scripts": {
    "dev": "webpack-dev-server --open --hot --inline --config ./webpack.config.js",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^4.2.1",
    "html-webpack-plugin": "^4.3.0",
    "style-loader": "^1.2.1",
    "vue-loader": "^15.9.3",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "vue": "^2.6.12",
    "vue-router": "^3.4.3"
  }
}

然后执行 $ npm run dev,自动打开了浏览器但是编译脚本报错:
在这里插入图片描述
在这里插入图片描述
找不到模块,Course.vue 和 Home.vue,排查后发现之前声明组件的时候 Home.vueCourse.vue 书写有误,修改 main.js:

import Vue from './vue'
// 一定要以vue结尾
import App from './App.vue'
import './index.css'
import VueRouter from 'vue-router'
// 如果基于模块化机制:Vue.use(VueRouter)
// 声明组件
import Home from './components/Home/Home.vue'
import Course from './components/Course/Course.vue'
//创建路由对象
const router = new VueRouter({
    // 配置路由信息
    routers: [
        {
            path: '/',
            name: 'Home',
            component: Home
        },
        {
            path: '/course',
            name: 'Course',
            component: Course
        },
    ]
})
let vm = new Vue({
    el: '#app',
    router: router,
    template: `
      <App></App>
    `,
    components: {
        App
    }
})

这个时候就可以正常编译了,编译后遇到下面的问题:
在这里插入图片描述
在这里插入图片描述
需要在 main.js 中加上 Vue.use(VueRouter)

import Vue from './vue'
// 一定要以vue结尾
import App from './App.vue'
import './index.css'
import VueRouter from 'vue-router'
// 基于模块化机制
Vue.use(VueRouter)
// 声明组件
import Home from './components/Home/Home.vue'
import Course from './components/Course/Course.vue'
//创建路由对象
const router = new VueRouter({
    // 配置路由信息
    routers: [
        {
            path: '/',
            name: 'Home',
            component: Home
        },
        {
            path: '/course',
            name: 'Course',
            component: Course
        },
    ]
})
let vm = new Vue({
    el: '#app',
    router: router,
    template: `<App></App>`,
    components: {
        App
    }
})

这里可以把 main.js 中的Vue的部分修改为:

let vm = new Vue({
    el: '#app',
    router: router,
    render: c => c(App)
    // template: `<App></App>`,
    // components: {
    //     App
    // }
})

在这里插入图片描述
在这里插入图片描述
Githubhttps://github.com/ThanlonSmith/SPA-Vue

20. css中scoped的使用

scoped可以使当前样式只在当前组件生效,如,

Course.vue:

<template>
  <div>
    课程列表!
  </div>
</template>
<!--组件的业务逻辑-->
<script>
export default {
  name: 'Course',
  data() {
    return {}
  },
}
</script>
<!--组件的样式-->
<style scoped>
* {
  color: orange;
}
</style>

Home.vue:

<template>
  <div>
    首页!
  </div>
</template>
<!--组件的业务逻辑-->
<script>
export default {
  name: 'Home',
  data() {
    return {}
  },
}
</script>
<!--组件的样式-->
<style scoped>
*{
  color: red;
}
</style>

在这里插入图片描述
在这里插入图片描述

class重复也是没有关系的!

21. vue-cli的使用

可使用的模块有:

  • webpack:一个功能齐全的 webpack + vue-loader 设置,具有热重载、linting、测试和css提取功能
  • webpack-simple:一个简单的 Webpack + vue-loader 设置,用于快速设计原型
  • browserify:全功能 browserify + vueify 设置,具有热重载,linting和单元测试功能
  • browserify-simple:一个简单的 browserify + vueify 设置,用于快速原型设计
  • pwa:基于 webpack 模板的 vue-cli 的 pwa 模板
  • simple:单个 html 文件中最简单的 Vue 设置
  • progress:滚动

使用脚手架创建一个基于 webpack-simple 模块的项目:

$ vue init webpack-simple my-project

? Project name my-project
? Project description A Vue.js project
? Author erics1996 <erics1996@yeah.net>
? License MIT
? Use sass? No

进入目录,安装需要的相关依赖包:

$ cd my-project
$ cnpm install
$ npm run dev

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
使用 $ cnpm i vue-router 下载路由,可以在src目录下创建router文件夹和index.js用来写路由相关信息:
在这里插入图片描述
将路由对象VueRouter 挂在到 Vue 实例,main.js:

import Vue from 'vue'
import App from './App.vue'
import router from './router/index.js' // 可以不用加js后缀,路由相关的信息在index.js中写

new Vue({
  router,
  el: '#app',
  render: h => h(App)
})

创建router目录用于存放路由相关的信息,创建componets用来存放组件:
在这里插入图片描述
index.js:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from "../components/Home/Home";
import Course from "../components/Course/Course";

Vue.use(VueRouter) // use相当于挂在父类
const router = new VueRouter({
  // 配置路由信息
  routes: [ // 这里不要写错了
    {
      path: '/',
      redirect: '/home'
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    },
    {
      path: '/course',
      name: 'Course',
      component: Course
    },
  ]
})
export default router

Home.vue:

<template>
  <div>我是首页!</div>
</template>
<script>
export default {
  name: 'Home',
  data() {
    return {}
  },
}
</script>
<style></style>

Course.vue:

<template>
  <div>我是课程列表页面!</div>
</template>
<script>
export default {
  name: 'Course',
  data() {
    return {}
  },
}
</script>
<style></style>

App.vue:

<template>
  <!--  <div id="app">-->
  <!--    <img src="./assets/logo.png">-->
  <!--    <h1>{{ msg }}</h1>-->
  <!--    <h2>Essential Links</h2>-->
  <!--    <ul>-->
  <!--      <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>-->
  <!--      <li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>-->
  <!--      <li><a href="https://chat.vuejs.org" target="_blank">Community Chat</a></li>-->
  <!--      <li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>-->
  <!--    </ul>-->
  <!--    <h2>Ecosystem</h2>-->
  <!--    <ul>-->
  <!--      <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>-->
  <!--      <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>-->
  <!--      <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>-->
  <!--      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>-->
  <!--    </ul>-->
  <!--  </div>-->
  <div id="app">
    <img src="./assets/logo.png">
    <h4>{{ msg }}</h4>
    <router-link :to="{name:'Home'}">首页</router-link>
    <router-link :to="{name:'Course'}">课程</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {
      msg: '基于webpack-simple模板构建!'
    }
  }
}
</script>
<style></style>

在这里插入图片描述
在这里插入图片描述
使用 webpack 模板来创建一个工程,

在这里插入图片描述
在这里插入图片描述
构建好的**工程目录结构:
在这里插入图片描述
同样使用 $ npm run dev 命令来运行:
在这里插入图片描述
默认找 index.js,可以不写后缀:

在这里插入图片描述
Vue.config.productionTip = false 的意思是生产环境不需要控制台有提示,@符号默认是 src 路径。
在这里插入图片描述

在这里插入图片描述

22. element-ui的使用

使用 $ cnpm i element-ui -S 安装 element-ui,使用 $ cnpm i 安装 element-ui 依赖的包,使用 element-ui 来布局 App.vue:

<template>
  <div id="app">
    <el-container>
      <el-header>
        <router-link :to="{name:'Home'}">首页</router-link>
        <router-link :to="{name:'Course',query:{userid:1}}">免费课程</router-link>
      </el-header>
      <el-main>
        <router-view/>
      </el-main>
    </el-container>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

main.js:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router' // 默认找index.js
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import '../static/global/index.css'

Vue.config.productionTip = false // 生产环境不需要控制台有提示
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: {App},
  template: '<App/>'
})

在这里插入图片描述
在这里插入图片描述

分享一个好用的Python学习网站https://pythoneers.cn/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值