Vue.js入门知识day4

本文深入讲解Vue.js的基础知识,包括小球动画实现、组件定义与传值、评论功能开发、DOM元素获取及路由管理等核心技能,助力前端开发者掌握Vue.js实践应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

复习:实现小球动画

1、html布局

<div id="app">
       <input type="button" value="加入购物车" @click="flag=!flag">
       <transition
       @before-enter="beforeEnter"
       @enter="enter"
       @after-enter="afterEnter"
       >
           <div class="ball" v-show="flag"></div>
       </transition>
   </div>

2、css样式

   <style>
        .ball{
            width: 15px;
            height: 15px;
            background-color: red;
            border-radius: 50%;
        }
    </style>

3、JavaScript代码

<script>

       //创建 Vue 实例,得到ViewModel
       var vm =new Vue({
           el:'#app',
           data:{
             flag:false
           },
           methods:{
               beforeEnter(el){
                   el.style.transform = 'translate(0,0)'
               },
               enter(el,done){
                   el.offsetWidth


                   el.style.transform = 'translate(150px,450px)'
                   el.style.transition = 'all 1s ease'
                   done()
               },
               afterEnter(el){
                   // 这句话,第一个功能,是控制小球的显示和隐藏
                   // 第二个功能:直接跳过后半场动画,让flag标识符直接变为false
                   // 当第二次再点击 按钮的时候,flag false -> true
                   this.flag = !this.flag
                   // el.style.opacity = 0.5
                   //Vue把一个完整的动画,使用钩子函数,拆分为了两部分;
                   //我们使用 flag标识符,来表示动画的切换;
                   //刚一开始,flag= false -> true -> false
               }
           }
       })
   </script>

复习:定义组件的方式

var login = {
	template:<h1>1234</h1>
}
var vm = new Vue({
	el:'#app',
	data:{},
	methods:{},
	components:{
		//'组件的名称':组件的模板对象
		//'mylogin':login
		login
	}
})

组件传值:父组件向子组件传值

1、html布局

<div id="app">
       <!--父组件可以在引用子组件的时候通过属性绑定(v-bind:)的形式,把需要传递给子组件的数据,以属性绑定的形式传递到子组件内部,供子组件使用-->
      <com1 v-bind:parentmsg="msg"></com1>
   </div>

2、JavaScript代码

 <script>
       //创建 Vue 实例,得到ViewModel
       var vm =new Vue({
           el:'#app',
           data:{
             msg:'123 这是父组件'
           },
           methods:{
           },
           components:{
               // 结论:经过演示,发现,子组件中,默认无法访问到父组件中的 data上的数据和methods中的方法
               com1:{
                   data(){//注意:子组件中的 data 数据,并不是通过父组件传递过来的,而是子组件自身私有的,比如:子组件通过Ajax,请求回来的数据,都可以放到 data 身上;
                       //data上的数据,都是可读可写的
                     return {
                         title:'123',
                         content:'qqq'
                     }
                   },
                   //注意:组件中的 所有 props 中的数据,都是通过父组件传递给子组件的
                   //props 中的数据,都是只读的,无法重新赋值
                   template:'<h1 @click="change">这是子组件 --- {{parentmsg}}</h1>',
                   props:['parentmsg'],//把父组件传递过来的 parentmsg 属性,先在 props 数组中,定义一下,这样才能使用这个数据
                    methods:{
                       change(){
                            this.parentmsg = "被修改了"
                        }
                    }

               }
           }
       })
   </script>

父组件把方法传递给子组件(子组件向父组件传值)

  • 把方法用v-on绑定在子组件上
  • 给input绑定点击事件
  • 在点击事件中用this.$exit调用方法
    1、html布局
  <div id="app">
     <!--父组件向子组件传递方法,使用的是事件绑定机制;v-on,当我们自定义了一个 事件属性之后,那么,子组件就能够,通过某些方式,来调用传递进去的这个方法了-->
      <com2 v-on:func="show"></com2>
   </div>
   <template id="tmp1">
       <div>
           <h1>这是子组件</h1>
           <input type="button" value="点击我,获得父组件的值" @click="sonMethod">
       </div>
   </template>

2、JavaScript代码

<script>
       // 定义了一个字面量类型的 组件模板对象
       var com2 = {
           template:'#tmp1',//通过指定了一个 Id,表示说,要去加载这个指定Id的 template元素中的内容,当做组件的HTML结构
           data:function () {
               return{
                   title:123
               }
           },
           methods:{
               sonMethod(){
                   //当点击子组件的按钮的时候,如何拿到父组件传递过来的 func方法,并调用这个方法?
                   //emit英文原意是触发、调用、发射的意思
                   this.$emit('func',this.title)
               }
           }

       };
       //创建 Vue 实例,得到ViewModel
       var vm =new Vue({
           el:'#app',
           data:{
               sonData:''
           },
           methods:{
               show(data){
                   console.log('这是父组件的数据'+data);
                   this.sonData = data;
               }
           },
           components:{
               // 结论:经过演示,发现,子组件中,默认无法访问到父组件中的 data上的数据和methods中的方法
                com2
           }
       })
   </script>

发表评论功能的实现

1、html布局

  <div id="app">
       <comment-box></comment-box>
       <ul class="list-group">
           <li class="list-group-item" v-for="item in list" :key="item.id">
               <span class="badge">评论人:{{item.user}}</span>
               {{item.content}}
           </li>
       </ul>
   </div>
    <template id="tmp1">
        <div>
            <div>
                <div class="form-group">
                    <label>评论人</label>
                    <input type="text" class="form-control" v-model="user"></div>
            </div>
            <div class="form-group">
                <label>评论内容</label>
                <textarea class="form-control" v-model="content"></textarea>
            </div>
            <div class="form-group">
                <input type="button" value="发表评论" class="btn btn-primary" @click="postComment">
            </div>
        </div>
    </template>

2、JavaScript代码

  var commentBox = {
           template:'#tmp1',
           data:function () {
               return{
                   user:'',
                   content:''
               }
           },
           methods:{
               postComment(){
                   // 1.评论数据存到哪里去?存放到了localStorage中 localStorage.setItem('cmts','')
                   // 2.先组织出一个最新的评论数据对象
                   // 3.想办法,把第二步中,得到的评论数据对象,保存到localStorage中;
                   //    3.1 localstorage 只支持存放字符串数据,要先调用JSON.stringify
                   //    3.2 在保存最新的评论之前,要先从 localStorage中获取到之前的评论数据(string),转换为一个数组后,把最新的评论unshift到这个数组
                   //    3.3 如果获取到的 localStorage 中的评论字符串为空不存在,则可以返回一个'[]',让JSON.parse去转换
                   //    3.4 把最新的评论列表数组,再次调用JSON.stringify 转为数组字符串,然后调用 localStorage.setItem()
                   var obj = {id:Date.now(),user:this.user,content:this.content}
                   var list = JSON.parse(localStorage.getItem('cmts')||'[]');
                   list.unshift(obj);
                   localStorage.setItem('cmts',JSON.stringify(list));
                   this.user=this.content='';

               }
           }
       }

       var vm =new Vue({
           el:'#app',
           data:{
               list:[
                   {id:Date.now(),user:'李白',content:'天生我材必有用'},
                   {id:Date.now(),user:'江小白',content:'劝君更尽一杯酒'},
                   {id:Date.now(),user:'小马',content:'我姓马'}
               ]
           },
           methods:{

           },
           components:{
                commentBox
           }
       })
   </script>

实现评论的发表和自动刷新列表

1、html布局

 <div id="app">
       <comment-box @func="loadComment"></comment-box>
       <ul class="list-group">
           <li class="list-group-item" v-for="item in list" :key="item.id">
               <span class="badge">评论人:{{item.user}}</span>
               {{item.content}}
           </li>
       </ul>
   </div>
    <template id="tmp1">
        <div>
            <div>
                <div class="form-group">
                    <label>评论人</label>
                    <input type="text" class="form-control" v-model="user"></div>
            </div>
            <div class="form-group">
                <label>评论内容</label>
                <textarea class="form-control" v-model="content"></textarea>
            </div>
            <div class="form-group">
                <input type="button" value="发表评论" class="btn btn-primary" @click="postComment">
            </div>
        </div>
    </template>

2、JavaScript代码

    <script>
       var commentBox = {
           template:'#tmp1',
           data:function () {
               return{
                   user:'',
                   content:''
               }
           },
           methods:{
               postComment(){
                   // 1.评论数据存到哪里去?存放到了localStorage中 localStorage.setItem('cmts','')
                   // 2.先组织出一个最新的评论数据对象
                   // 3.想办法,把第二步中,得到的评论数据对象,保存到localStorage中;
                   //    3.1 localstorage 只支持存放字符串数据,要先调用JSON.stringify
                   //    3.2 在保存最新的评论之前,要先从 localStorage中获取到之前的评论数据(string),转换为一个数组后,把最新的评论unshift到这个数组
                   //    3.3 如果获取到的 localStorage 中的评论字符串为空不存在,则可以返回一个'[]',让JSON.parse去转换
                   //    3.4 把最新的评论列表数组,再次调用JSON.stringify 转为数组字符串,然后调用 localStorage.setItem()
                   var obj = {id:Date.now(),user:this.user,content:this.content}
                   var list = JSON.parse(localStorage.getItem('cmts')||'[]');
                   list.unshift(obj);
                   localStorage.setItem('cmts',JSON.stringify(list));
                   this.user=this.content='';
                   this.$emit('func');
               }
           }
       }
       var vm =new Vue({
           el:'#app',
           data:{
               list:[
                   {id:Date.now(),user:'李白',content:'天生我材必有用'},
                   {id:Date.now(),user:'江小白',content:'劝君更尽一杯酒'},
                   {id:Date.now(),user:'小马',content:'我姓马'}
               ]
           },
           methods:{
                loadComment(){
                    this.list = JSON.parse(localStorage.getItem('cmts')||'[]');
                }
           },
           created(){
               this.loadComment();
           },
           components:{
                commentBox
           }
       })
   </script>

使用ref获取DOM元素和组件引用

1、html布局

<div id="app">
       <input type="button" value="获取元素" @click="getElement">
       <h3 id="myh3" ref="myh3">哈哈哈,今天天气太好了</h3>
        <login ref="mylogin" ></login>
   </div>

2、JavaScript代码

 <script>
       var login = {
           template:'<h1>登录组件</h1>',
           methods: {
               show(){
                   console.log('这是子方法')
               }
           }
       }
       var vm =new Vue({
           el:'#app',
           data:{},
           methods: {
               getElement(){
                   this.$refs.mylogin.show();
               }
           },
           components:{
                login
           }
       })
   </script>

路由:前端路由和后端路由的概念

什么是路由?

  • 后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源。
  • 前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:http请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现
  • 在单页面应用程序中,这种通过hash来切换页面的方式,称作前端路由(区别于后端路由);

相关文件

URL中的hash(井号)

路由:vue-router的基本使用

1、html布局

<div id="app">
       <a href="#/login">登录</a>
       <a href="#/register">注册</a>
       <!--这是vue-router提供的元素,专门用来 当做占位符的,将来,路由规则,匹配到的组件,就会展示到 这个router-view 中去-->
       <!--所以:我们可以把 router-view 认为是一个占位符-->
        <router-view></router-view>
   </div>

2、JavaScript代码

<script>
       // 组件的模板对象
       var login = {
           template:'<h1>登录组件<h1>'
       }

       var register = {
           template: '<h1>注册组件</h1>'
       }
        // 2.创建一个路由对象,当导入 vue-router包之后,在window全局对象中,就有了一个路由的构造函数,叫做 VueRouter
        // 在new 路由对象的时候,可以为构造函数传递一个配置对象
       var routerObj = new VueRouter({
           //route //这个配置对象中的 route 表示 【路由匹配规则】的意思
           routes:[//路由匹配规则
               //每个路由匹配规则,都是一个对象,这个规则对象,身上必须有两个必须的属性;
               //属性1 是path ,表示监听哪个路由链接地址
               //属性2 是component,表示,如果路由是前面匹配到的path,则展示 component属性对应的那个组件
               //注意:component的属性值,必须是一个组件的模板对象,不能是一个组件的引用名称
               {path:'/login',component:login},
               {path:'/register',component:register}
           ]
       })
       var vm =new Vue({
           el:'#app',
           data:{},
           methods: {

           },
          router:routerObj//将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
       })
   </script>

路由:vue-link的使用

为什么要使用router-link?

因为官方是不建议手动打#号的。

1、html布局

  <div id="app">
       <!--<a href="#/login">登录</a>-->
       <!--<a href="#/register">注册</a>-->
       <!--router-link默认渲染为一个 a标签-->
       <!--也可以通过tag="span"渲染为一个span标签,但是不管渲染为什么标签,在router-link内部永远为他绑定了一个点击的触发事件,去实现路由的切换-->
       <router-link to="/login" tag="span">登录</router-link>
       <router-link to="/register">注册</router-link>
        <router-view></router-view>
   </div>

路由:redirect重定向的使用

为什么要使用redirect?

强制展示某个组件
1、JavaScript代码

 <script>
       // 组件的模板对象
       var login = {
           template:'<h1>登录组件<h1>'
       }

       var register = {
           template: '<h1>注册组件</h1>'
       }
               // {path:'/',component:login},
               //不推荐,因为会让用户对根路径和登录组件产生误解
               {path:'/',redirect:'/login'},//这里的 redirect 和 Node中的redirect完全是两码事
               {path:'/login',component:login},
               {path:'/register',component:register}
           ]
       })
       var vm =new Vue({
           el:'#app',
           data:{},
           methods: {

           },
          router:routerObj//将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
       })
   </script>

设置选中路由高亮的两种方式

  • 用默认类设置
<style>
        .router-link-active{
            color: red;
            font-weight: 800;
            font-style: italic;
            font-size: 80px;
            text-decoration: underline;
            background-color: green;
        }
    </style>
  • 用自定义类

linkActiveClass:'类名’

  <script>
       // 组件的模板对象
       var login = {...}
       var routerObj = new VueRouter({
           routes:[ ... ],
           linkActiveClass:'myactive'
       })
       var vm =new Vue({... })
   </script>

为路由切换启动动画

  • 把router-view放在transition内部
  • style设置动画

1、html布局

 <div id="app">
       <router-link to="/login" tag="span">登录</router-link>
       <router-link to="/register">注册</router-link>
       <transition mode="out-in">
            <router-view></router-view>
       </transition>
   </div>

2、css样式

 <style>
        .router-link-active,.myactive{
            color: red;
            font-weight: 800;
            font-style: italic;
            font-size: 80px;
            text-decoration: underline;
            background-color: green;
        }
        .v-enter,
        .v-leave-to{
            opacity: 0;
            transform: translateX(140px);
        }
        .v-enter-active,
        .v-leave-active{
            transition:all 0.5s ease;
        }
    </style>

使用query方式传递参数(方式1)

1、html布局

 <div id="app">
       <!--如果在路由中,使用查询字符串给路由传递参数,则不需要修改路由规则的 path属性-->
       <!--传递两个参数就用&连接-->
       <router-link to="/login?id=10&name=wh" tag="span">登录</router-link>
       <router-link to="/register">注册</router-link>
        <router-view></router-view>
   </div>

2、JavaScript代码

 <script>
       // 组件的模板对象
       var login = {
           template:'<h1>登录组件---{{$route.query.id}}---{{$route.query.name}}</h1>',
           created(){//组件的生命周期钩子函数
             //  console.log(this.$route.query.id);
           }
       }

       var register = {
           template: '<h1>注册组件</h1>'
       }
       var routerObj = new VueRouter({
           routes:[
               {path:'/login',component:login},
               {path:'/register',component:register}
           ]
       })
       var vm =new Vue({
       })
   </script>

使用params方式传递参数(方式2)

1、html布局

 <div id="app">
      <!--注意,传的值的个数要和path的参数一一对应-->
       <!--多个是用/-->
       <router-link to="/login/12/wh" tag="span">登录</router-link>
       <router-link to="/register">注册</router-link>
       <transition>
            <router-view></router-view>
       </transition>
   </div>

2、JavaScript代码

<script>
       // 组件的模板对象
       var login = {
           template:'<h1>登录组件</h1>',
           created(){
               console.log(this.$route.params.id)
               console.log(this.$route.params.name)
           }
       }
       var register = {
           template: '<h1>注册组件</h1>'
       }
       var routerObj = new VueRouter({
           routes:[
               {path:'/login/:id/:name',component:login},
               {path:'/register',component:register}
           ]
       })
       var vm =new Vue({
       })
   </script>

使用children属性实现路由嵌套

1、html布局

  <div id="app">
       <router-link to="/account">Account</router-link>
       router
       <!--router-view是一个容器,装载的的account内部的内容-->
       <router-view></router-view>
   </div>
   <template id="tmp1">
       <div>
           <h1>这是Account组件</h1>
           <router-link to="/account/login">登录</router-link>
           <router-link to="/account/register">注册</router-link>
           <!--router-view是一个容器,装载的是login组件或者register组件-->
           <router-view></router-view>
       </div>
   </template>

2、JavaScript代码

<script>
       // 组件的模板对象
       var account = {
           template:'#tmp1'
       }
       var login = {
           template:'<h3>登录</h3>'
       }
       var register = {
           template:'<h3>注册</h3>'
       }
       //创建 Vue实例,得到ViewModel
       var router = new VueRouter({
           routes:[
               {
                   path:'/account',
                   component:account,
                   // 使用children属性,实现子路由,同时,子路由的path前面,不要带/,否则永远以根路径开始请求,这样不方便我们用户去理解URL地址
                   children:[
                       {path:'login',component: login},
                       {path:'register',component:register}
                   ]
               }
           ]
       })
       var vm =new Vue({
           el:'#app',
           data:{},
           methods: {},
           router:router//将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
       })
   </script>

使用命名视图实现经典布局

1、html布局

 <div id="app">
       <router-view></router-view>
       <!--这些命名字符的名称是字符串-->
       <router-view name="left"></router-view>
       <router-view name="main"></router-view>
   </div>

2、JavaScript代码

 <script>
       var header = {
           template:'<h1>Header头部区域</h1>'
       }
       var leftBox = {
           template: '<h1>Left侧边栏区域</h1>'
       }
       var mainBox = {
           template:'<h1>Main主体区域</h1>'
       }

       // 创建路由对象
       var router = new VueRouter({
           routes:[
               {path:'/',components:{
                   default:header,
                   left:leftBox,
                   main:mainBox
               }}
           ]
       })
       var vm =new Vue({
           el:'#app',
           data:{},
           methods: {},
           router:router//将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
       })
   </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值