Vue2 基础入门

介绍

  • Vue 是一套构建用户界面的渐进式框架
  • Vue 只关注视图层, 采用自底向上增量开发的设计
  • 特点:
    • 采用组件化模式,提高代码复用率、且让代码更好维护
    • 声明式编码,让编码人员无需直接操作DOM,提高开发效率
    • 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点。

Vue2 基础

起步

编程工具:VSCode (插件LiveServer)

开发版本Vue.js:安装 — Vue.js

 基础示例

    <!-- {{ }}:插值表达式,可以直接引入data 中的数据,并将其渲染到页面上. -->
    <div id="app">
        {{ message }}
    </div> 

    <script>
        /**
         * Vue实例化对象 构造的写法格式类似于 ajax
         * el:指定渲染的元素,可以是选择器字符串,也可以是元素对象(建议 ID 选择器)
         * data:数据对象,包含了页面上需要渲染的数据
         */
        var app = new Vue({
            el: "#app",
            data: {
                message: "hello Vue!"
            }
        });
    </script>

内容绑定 v-text 、 v-html

  • v-text 设置标签文本值
  • v-html 设置标签的 innerHTML
    <div id="app">
        <p v-text="message"></p>
        <div v-html="htmlContent"></div>
    </div> 
    <script>
        var app = new Vue({
            el: "#app",
            data: {
                message: "hello Vue!",
                htmlContent:"<h1>This is a heading</h1>"
            }
        });
    </script>

事件绑定 v-on

    <div id="app">
        <!-- v-on:click 和 @click 绑定点击事件 -->
        <input type="button" value="点击加一" v-on:click="counter += 1">
        <input type="button" value="点击加一" @click="counter += 1">
        <!-- v-on:dblclick 和 @dblclick 绑定双击事件 -->
        <input type="button" value="双击加二" @dblclick="addTwo()">
        <p>这个按钮被点击了 {{ counter }} 次。</p>
    </div>
    <script>
        let app = new Vue({
            el: "#app",
            data: {
                counter: 0
            },
            methods: {
                // v-on: 绑定事件 在 methods 中定义 ,方法内的 this 指向当前 Vue 实例
                addTwo:function(){
                    this.counter += 2;
                }
            }
        });
    </script>

事件修饰符

  • .stop - 阻止冒泡
  • .prevent - 阻止默认事件
  • .capture - 阻止捕获
  • .self - 只监听触发该元素的事件
  • .once - 只触发一次
  • .left - 左键事件
  • .right - 右键事件
  • .middle - 中间滚轮事件
<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联  -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件侦听器时使用事件捕获模式 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>
<!-- click 事件只能点击一次,2.1.4版本新增 -->
<a v-on:click.once="doThis"></a>

按键修饰符

  • 对键盘按键事件进行修饰,keyup(按下键盘立即触发),keydown(抬起键盘立即触发)
  • 可以链式调用,如 @keyup.enter.tab.esc ,同时捕获三个键,捕获到任意一个都会触发
  • .exact 修饰符允许控制由精确的系统修饰符组合触发的事件
  • 全部的按键别名:
    • .enter
    • .tab
    • .delete (捕获 "删除" 和 "退格" 键)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right
  • 系统修饰键:
    • .ctrl
    • .alt
    • .shift
    • .meta
<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

计算属性 computed

在Vue中处理 “计算” 任务

    <div id="app">
        <p>计算后反转字符串: {{ reversedMessage }}</p>
        <p>原始字符串: {{ message }}</p>
    </div>
       
    <script>
    var vm = new Vue({
        el: '#app',
        data: {
          message: 'Runoob!'
        },
        computed: {
          // 计算属性
          // computed 选项定义 getter 函数,getter 函数的返回值会根据它的依赖跟踪的变量变化而动态更新
          // 这里的 getter 函数返回的结果会绑定到页面的 DOM 上,所以我们可以直接将它用在模板中
          // computed 有缓存,只有当它的依赖值发生变化时,才会重新求值。
          // 而使用 methods,每次调用都会重新执行函数,导致页面渲染变慢
          reversedMessage: function () {
            // `this` 指向 vm 实例
            return this.message.split('').reverse().join('')
          }
        }
    })
    </script>

 样式绑定 v-bind

    <style>
        .active {
            width: 100px;
            background: green;
        }
        .text-danger {
            width: 100px;
            background: red;
        }
    </style>

    <div id="app">
        <!-- v-bind:属性名=表达式 用于绑定属性值 -->
        <div v-bind:class="{ 'active': isActive }">hello world</div>
        <div :class="classObject">helllo world</div>
        <img v-bind:src="imgSrc" class="active" alt="">
    </div>
    <script>
        new Vue({
        el: '#app',
        data: {
          isActive: true,
          error: {
            value: true,
            type: 'fatal'
          },
          imgSrc: 'https://cn.vuejs.org/images/logo.png'
        },
        computed: {
          classObject: function () {
            return {
                base: true,
                active: this.isActive && !this.error.value,
                'text-danger': this.error.value && this.error.type === 'fatal',
            }
          }
        }
      })
    </script>

 条件渲染 v-if 、 v-show

    <div id="app">
        <!-- v-show 和 v-if 的区别 -->
        <!-- v-show 只是简单地切换元素的 display:none 和 display:block 样式,不会销毁或重建元素,因此对性能有一定的影响。 -->
        <!-- v-if 是真正的条件渲染,它会销毁或重建元素,因此对性能有更大的影响。 -->
        <!-- 因此,在条件不频繁的情况下,建议使用v-if,在条件频繁的情况下,建议使用 v-show。 -->
        <p v-show="seen">现在你看到我了!</p>
        <p v-if="seen">现在你看到我了!!</p>
        <p v-else-if="seen">你还没有看到我???</p>
        <p v-else>你还没有看到我!!!</p>
        <button @click="seen =!seen">点我切换</button>
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        seen: true,
      }
    })
    </script>

循环结构 v-for

    <div id="app">
        <ul>
            <!-- v-for="(value, key, index) in object" -->
            <!-- value: 当前值,key: 当前键,index: 当前索引 -->
            <!-- v-for 遍历对象或者数组 -->
            <li v-for="(value, key, index) in object" :key="value" >
                {{ index }}. {{ key }}:
                <ul v-if="value instanceof Object" >
                    <li v-for="(value1, key1) in value" :key="value1" >
                        <span v-if="value instanceof Array == false" > {{ key1 }}: </span> 
                       {{ value1 }}
                    </li>
                </ul>
                <span v-else>
                     {{ value }}
                </span> 
            </li>
        </ul>
      </div>
       
      <script>
      new Vue({
        el: '#app',
        data: {
          object: {
            name: '张三',
            age: 18,
            gender: '男',
            hobbys: ['打篮球', '看电影', '唱歌'],
            address: {
              city: '北京',
              country: '中国'
            }
          }
        }
      })
      </script>

表单双向绑定 v-model

    <div id="app">
        <!-- v-model实现输入框与data中的message绑定 -->
        <!-- 当输入框内容发生变化时,会自动更新data中的message -->
        <input type="text" v-model="message" @keyup.enter="show">
        <!-- 当data中的message发生变化时,会自动更新输入框中的内容 -->
        <button v-on:click="reverseMessage">反转字符串</button>
    </div>
    <script>
        let app = new Vue({
            el: "#app",
            data: {
                message: "Hello Vue.js!"
            },
            methods: {
                show: function () {
                    alert(this.message);
                },
                reverseMessage: function () {
                    this.message = this.message.split('').reverse().join('')
                }
            }
        });
    </script>

组件化开发

一个应用中只能存在一个 Vue 实例.

Vue 提供了 Component 组件,不仅减少了 Vue 实例的代码量,还可以实现复用.

全局组件

所有实例都能用全局组件。

    <div id="app">
        <!-- 使用组件 -->
        <register></register>
    </div>
 
    <script>
        //定义全局组件
        Vue.component('register', {
            template: `<div><h1>注册</h1><span>{{msg}}</span><button @click="test">测试</button><p>计算属性:{{counterSqrt}}</p><comp></comp></div>`,
            data() { //组件中定义数据,必须函数的形式
                return { //返回值是一个对象,对象内部就是数据
                    msg: "我是注册全局组件中的数据",
                    count: 2
                }
            },
            methods: { 
                test() {
                    console.log("我是组件中的方法");
                }
            },
            computed: {
                counterSqrt() {
                    return this.count * this.count;
                }
            },
            components: { //给组件中定义一些组件
                comp: {
                    template: `<div>我是全局组件的子组件</div>`
                }
            },
            beforeCreate() { //组件生命周期 创建之前 
                console.log("beforeCreate:", this.msg);//此时 msg 因该是 undefine
            },
            created() { //组件生命周期 创建
                console.log("created:", this.msg);
            },
        });
 
        const app = new Vue({ //组件生效的前提是要有 Vue 实例, 并在实例的作用域中使用
            el: "#app"
        });
    </script>

局部组件

在实例选项中注册局部组件,这样组件只能在这个实例中使用

    <div id="app">
        <login></login>
        <reg></reg>
    </div>
 
    <script>
 
        //定义局部组件
        //在子组件中不可使用父组件的数据! 比如 parent 数据
        const login = {
            template: `<div><div>{{ child }}</div><comp></comp><hr></div>`,
            data() {
                return {
                    child: "我是注册组件的子组件 login 中的数据",
                }
            },
            components: { //给组件中定义一些组件
                comp: {
                    template: `<div>我是login的子组件</div>`
                }
            },
            
        }
 
        let app = new Vue({
            el: "#app",
            data: {
                parent: "我是父组件中的数据"
            },
            components: { //注册组件
                login, //单独在外面定义,然后引入
                reg: {  //直接在这里定义
                    template: `<div><div>{{ child }}</div></div>`,
                    data() { //注意组件中数据的写法
                        return {
                            child: "我是子组件 reg 中的数据"
                        }
                    }
                }
            }
        });
    </script>

Prop 组件传数据

    <div id="app">
        <div>
            <!-- 向子组件中传递动态数据:
            1.在组件标签上声明 key=value (key 是自定义的,value 就是 Vue 实例中的 data),子组件内部使用 props 数组声明 key 
            2.声明的自定义 key 可以通过 v-bind 进行属性的动态绑定
            3.Vue 官方明确提出只允许单向数据流,也就是只能从父传递到子,否则会报警告
             -->
          <input v-model="parentMsg">
          <br>
          <child v-bind:message="parentMsg"></child>
        </div>
    </div>
     
    <script>
    // 注册
    Vue.component('child', {
      // 声明 props
      props: ['message'],//用来接收父组件传来的数据, 这就相当于在子组件的 data 中添加了这个静态数据
      // 同样也可以在 vm 实例中像 "this.message" 这样使用
      template: '<span>{{ message }}</span>',
      data() {
            return {
                //这里相当于添加了 message: "......"
            }
          },
    })
    // 创建根实例
    new Vue({
      el: '#app',
      data: {
        parentMsg: '父组件内容'
      }
    })
    </script>

组件调用事件

    <div id="app">
        <!-- 父向子传递事件:在组件标签上定义 @key=value (@自定义事件名=父组件中的事件名) 即可 -->
        <login @aa="testParent()" @bb="testParent2" @cc="testParent3"></login>
    </div>
 
    <script>
        const login = {
            template: `<div><h2>登录</h2><button @click="testChild()">点给我调用父组件中的事件</button></div>`,
            data() {
                return {
                    count: 1
                }
            },
            methods: {
                testChild() {
                    alert("我是子组件中的事件!");
                    //通过 this.$emit 来调用父组件中的事件 
                    //参数1:组件标签上定义的事件名
                    //后续参数: 参数1 后面还可以继续传递参数,作为父组件事件中的参数
                    this.$emit("aa");
                    this.$emit("bb", this.count); //Vue 官方说只能单向传递(父传子),但是这种方式可以实现
                    this.$emit("cc", { count: this.count, name: "zhangsan", isGood: true });
                }
            }
        }
 
        const app = new Vue({
            el: "#app",
            methods: {
                testParent() {
                    alert("1.我是父组件中的事件!");
                },
                testParent2(count) {
                    alert("2.我是父组件中的事件!");
                    console.log("获取到子组件的值:" + count);
                },
                testParent3(obj) {
                    alert("3.我是父组件中的事件!");
                    console.log("获取到子组件的值: count=" + obj.count + ", name=" + obj.name + ", isGood=" + obj.isGood);
 
                }
            },
            components: {
                login
            }
        });
    </script>

插槽 slot

    <div id="app">
        <!-- 插槽: 用来扩展现有组件 -->
        <login></login>
        <!-- 默认: 会将信息填入所有插槽 -->
        <hr>
        <login><span>hello</span></login>
        <!-- 具名插槽: 给 slot 标签添加 name 属性作为身份标识  -->
        <hr>
        <login><button slot="a" @click="parent()">点我</button></login>
    </div>
 
    <script>
        const login = {
            template: `<div><h1>登录</h1><slot name="a"></slot></div>`,
        }
 
        const app = new Vue({
            el: "#app",
            methods: {
                parent() {
                    alert("我是父组件的事件");
                }
            },
            components: {
                login
            }
        });
    </script>

路由Router

安装 vue-router.js:  https://cdn.staticfile.net/vue-router/2.7.0/vue-router.min.js

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
    <title>Vue 测试实例 </title>
    <script src="./vue.js"></script>
    <script src="./vue-router.min.js"></script>
</head>
<body>
    <div id="app">
        <h1>Hello App!</h1>
        <p>
            <!-- 使用 router-link 组件来导航. -->
            <!-- 通过传入 `to` 属性指定链接. -->
            <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
            <router-link to="/foo">Go to Foo</router-link>
            <router-link to="/bar">Go to Bar</router-link>
        </p>
        <!-- 5.路由出口 -->
        <!-- 路由匹配到的组件将渲染在这里 -->
        <router-view></router-view>
    </div>

    <script>
    // 0. 如果使用模块化机制编程,導入Vue和VueRouter,要调用 Vue.use(VueRouter)

    // 1. 定义(路由)组件。
    // 可以从其他文件 import 进来
    const Foo = { template: '<div>foo</div>' }
    const Bar = { template: '<div>bar</div>' }

    // 2. 定义路由
    // 每个路由应该映射一个组件。 其中"component" 可以是
    // 通过 Vue.extend() 创建的组件构造器,
    // 或者,只是一个组件配置对象。
    // 我们晚点再讨论嵌套路由。
    const routes = [
        { path: '/foo', component: Foo },
        { path: '/bar', component: Bar }
    ]

    // 3. 创建 router 实例,然后传 `routes` 配置
    // 你还可以传别的配置参数, 不过先这么简单着吧。
    const router = new VueRouter({
        routes // (缩写)相当于 routes: routes
    })

    // 4. 创建和挂载根实例。
    // 记得要通过 router 配置参数注入路由,
    // 从而让整个应用都有路由功能
    const app = new Vue({
        router
    }).$mount('#app')
    </script>
</body>
</html>

路由切换方式

标签切换

     <div id="app">
        <!-- 1.链接 -->
        <a href="#/foo">Go to Foo</a>
        <a href="#/bar">Go to Bar</a>
        <hr>
        <!-- 2.标签  必须要有 to 属性, to="路由路径" -->
        <router-link to="/foo">Go to Foo</router-link>
        <router-link to="/bar">Go to Bar</router-link>
        <hr>
        <!-- 3.标签 -->
        <router-link :to="{path: '/foo'}">Go to Foo</router-link>
        <router-link :to="{path: '/bar'}">Go to Bar</router-link>
        <hr>
        <!-- 4.标签  根据路由对象 name 属性来切换路由 -->
        <!-- 推荐:路由随时可能会变,而命名不会变,因此可以起到解耦合的作用 -->
        <router-link :to="{name: 'Foo'}">Go to Foo</router-link>
        <router-link :to="{name: 'Bar'}">Go to Bar</router-link>

        <router-view></router-view>
    </div>

    <script>       
        const Foo = { template: '<div>foo</div>' }
        const Bar = { template: '<div>bar</div>' }
 
        const router = new VueRouter({
            routes: [
                //name 表示这个路由对象的唯一身份标识
                { path: '/foo', component: Foo, name: "Foo" },
                { path: '/bar', component: Bar, name: "Bar" },
            ]
        });

        new Vue({
            el: '#app',
            router
        }).$mount('#app')
    </script>

js切换

    <div id="app">
        <button @click="goToFoo()">go to foo</button>
        <button @click="goToBar()">go to bar</button>
        <router-view></router-view>
    </div>

    <script>       
        const Foo = { template: '<div>foo</div>' }
        const Bar = { template: '<div>bar</div>' }
 
        const router = new VueRouter({
            routes: [
                //name 表示这个路由对象的唯一身份标识
                { path: '/foo', component: Foo, name: "Foo" },
                { path: '/bar', component: Bar, name: "Bar" },
            ]
        });

        new Vue({
            el: '#app',
            methods: {
                goToFoo() {
                    // this.$router.push("/foo");//不推荐
                    // this.$router.push({ path: '/foo' });//不推荐
                    this.$router.push({ name: "Foo" });//推荐使用名称切换
                },
                goToBar() {
                    this.$router.push({ name: "Bar" });
                }
            },
            router
        }).$mount('#app')
    </script>

路由传参

query 传参

    <div id="app">
        <!-- query -->
        <a href="#/login?name=张三&password=123456">登录</a>
        <router-link to="/login?name=张三&password=123456">登录</router-link>
        <router-link :to="{path: '/login', query:{name:'张三', password:123456}}">登录</router-link>
        <router-link :to="{name: 'Login', query:{name:'张三',password:123456}}">登录</router-link>

        <router-view></router-view>
    </div>

    <script>       
        const login = {
            template: `<div><h1>登录功能</h1></div>`,
            created() { //生命周期:已执行完 组件内部事件 和 生命周期函数注册,自身的 data、methods、computed 属性注入和校验
                //通过 querystring 获取参数 
                // this.$route 代表当前路由对象 route.
                // this.$router 代表路由管理器对象 VueRouter
                console.log(this.$route); //获取当前路由对象
                console.log(this.$route.query.name);
                console.log(this.$route.query.password);
            }
        }
 
                //创建路由对象
        const router = new VueRouter({
            routes: [
                //querystring 传参
                { path: '/login', component: login, name: "Login" }
            ]
        });

        new Vue({
            el: '#app',
            router
        }).$mount('#app')
    </script>

restful 传参

    <div id="app">
        <!-- restful -->
        <a href="#/register/zhangsan/123456">注册</a>
        <router-link :to="{path: '/register/zhangsan/123456'}">注册</router-link>
        <router-link :to="{name: 'Register', params:{name:'zhangsan', password:123456}}">注册</router-link>

        <router-view></router-view>
    </div>

    <script>       
        const register = {
            template: `<div><h1>注册功能</h1></div>`,
            created() {
                //通过 restful 获取参数
                console.log(this.$route); //获取当前路由对象
                console.log(this.$route.params.name);
                console.log(this.$route.params.password);
            }
        }
 
                //创建路由对象
        const router = new VueRouter({
            routes: [
                //restful 传参
                { path: '/register/:name/:password', component: register, name: "Register" },
            ]
        });

        new Vue({
            el: '#app',
            router
        }).$mount('#app')
    </script>

嵌套路由

    <div id="app">
        <router-link to="/users">用户列表</router-link>
        <router-view></router-view>
    </div>

    <template id="users">
        <div>
            <h3>用户列表</h3>
            <router-link :to="{name:'adduser'}">添加用户信息</router-link>
            <table border="1">
                <tr>
                    <td>id</td>
                    <td>name</td>
                </tr>
                <tr>
                    <td>{{ users.id }}</td>
                    <td>{{ users.name }}</td>
                </tr>
            </table>
            <!-- 显示嵌套子组件 -->
            <router-view></router-view>
        </div>
    </template>
 
    <template id="add-user">
        <div>
            <div>
                <span>id: </span>
                <input type="text">
            </div>
            <div>
                <span>name: </span>
                <input type="text">
            </div>
            <button @click="submit()">提交</button>
        </div>
    </template>
 
    <script>
 
        //用户列表
        const users = {
            template: '#users',
            data() {
                return {
                    users: [] //这里不能写死,需要请求后端得到参数
                }
            },
            created() {
                //在组件构建完成后,请求后端得到 users 的所有数据,覆盖空数组
                this.users = { id: 1, name: '张三' }
            }
        }
 
        //添加用户
        const adduser = {
            template: '#add-user',
            methods: {
                submit() {
                    //向后端发送请求
                    //提交完成后切换路由
                    this.$router.push({ name: 'users' });
                }
            }
        }

        //创建路由对象
        const router = new VueRouter({
            routes: [
                {
                    path: '/users', component: users, name: 'users',
                    children: [  //嵌套子组件路由
                        //注意:嵌套路由中,子路由不能使用 / 开头
                        { path: 'adduser', name: 'adduser', component: adduser } //可以通过 /users/useradd 访问到此
                    ]
                },
            ]
        });

        const app = new Vue({
            el: '#app',

            components: {
                users,
                adduser
            },
            router
        })
    </script>

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值