Vue.js 3.0快速入门(附电影购票APP开发实战源码)

前言

文档笔记来源:kuangshenstudy,清华大学出版社,结合视频资源食用更佳,相关资源源码在文末,有需要自取。

一、概述

Vue是什么?

Vue.js是基于JavaScript的一套MVVC的前端框架。集合了众多优秀的主流框架设计思想,轻量、数据驱动(默认单向数据绑定,但也支持双向数据绑定)、学习成本低。 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

MVVM是什么?

MVVM层实现了前后端更好的分离(前端需要的数据只需要请求后端的接口即可)。
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。vm指定的是ViewModel,是视图模型。

ViewModel是MVVM模式的核心,是连接View和Model的桥梁。它有两个方向:

  1. 将模型转化成试图,将后端传递的数据转化成用户看到的界面。
  2. 将试图转化成模型,即将所看到的页面转化成后端的数据。
    在Vue.js框架中这两个方向都实现了,就是Vue.js中数据的双向绑定。
    在这里插入图片描述
    在这里插入图片描述

MVVM模式的实现者

Model:模型层, 在这里表示JavaScript对象
View:视图层, 在这里表示DOM(HTML操作的元素)
ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者

为什么要使用MVVM

MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处

低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
可复用:可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。
可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
在这里插入图片描述

二、Here we go!

1、第一个Vue程序(基于idea安装vus插件开发)

1.1引用vue.js 使用cdn导入

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

或者

<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

不推荐新手直接使用 vue-cli

1.2创建一个空项目,创建一个文件夹,new一个HTML文件

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:

(模板块,后期可直接复制模板)

<div id="app">
  {{ message }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

万物始于hello word 创建第一个 vue.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>

<body>

<!--view层,模板-->
<div id="app">
    <!--    数据绑定-->
    {{message}}
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        /*Model:数据*/
        data:{
        message:"hello vue~"
        }
    });
</script>

</body>
</html>

说明:

  • el:“#app” -----> 绑定元素的ID
  • data:{message:“hello vue~”} ----> 数据对象中有一个名为message的属性,并设置了初始值 hello,vue ~
  • {{message}} -----> 实现数据绑定功能
    在这里插入图片描述
    测试:

为了能够更直观的体验Vue带来的数据绑定功能, 我们需要在浏览器测试一番, 操作流程如下:
  1、在浏览器上运行第一个Vue应用程序, 进入开发者工具
  2、在控制台输入vm.message=‘HelloWorld’, 然后回车, 你会发现浏览器中显示的内容会直接变成HelloWorld,不需要刷新页面
  此时就可以在控制台直接输入vm.message来修改值, 中间是可以省略data的, 在这个操作中, 我并没有主动操作DOM, 就让页面的内容发生了变化, 这就是借助了Vue的数据绑定功能实现的; MV VM模式中要求View Model层就是使用观察者模式来实现数据的监听与绑定, 以做到数据与视图的快速响应。
  在这里插入图片描述

2、熟悉ES 6的语法

2.1为什么要使用ES 6

ES6是一次重大的版本升级,与此同时,由于ES6秉承着最大化兼容已有代码的设计理念,过去编写的 JS 代码还能正常运行。事实上,许多浏览器已经支持部分ES6特性,并继续努力实现其余特性。这意味着,在一些已经实现部分特性的浏览器中,开发者符合标准的 JavaScript 代码已经可以正常运行,可以更加方便地实现很多复杂的操作,提高开发人员的工作效率。
以下是ES6排名前十位的最佳特性列表(排名不分先后)

  • Default Parameters (默认参数)
  • Template Literals (模板文本)
  • Multi - line Strings (多行字符串)
  • Destructuring Assignment (解构赋值)
  • Enhanced Object Literals (增强的对象文本)
  • Arrow Functions (箭头函数)
  • Promises
  • Block - Scoped Constructs Let and Const (块作用域构造 Let and Const )
  • Classes(类)
  • Modules(模块)

2.2块作用域构造let和const

块级声明用于声明在指定块的作用域之外无法访问的变量。这里的块级作用域是指函数内部或
者字符{}内的区域。
在ES6中, let 是一种新的变量声明方式。在函数作用域或全局作用域中,通过关键字 var 声明
的变量,无论在哪里声明,都会被当成在当前作用域顶部声明的变量。

 function calculateTotalAmount ( vip )(
//只能使用 var 方式定义变量
 var amount =0;
 if ( vip ){
 //在此定义会被覆盖
 var amount=1;
  //在此定义会被覆盖
 var amount=100;
  //在此定义会被覆盖
  var amount=1000;
  return amount;
 } //打印内容
 console.log(calculateTotal/^mount (true));

以上结果将返回1000,这是一个bug,在ES 6中,用let限制块级作用域,而var限制函数作用域。

funetion calculateTotalAmount(vip){
//使用 var 方式定义变量 var amount =0;
 if(vip){
//使用1et定义的局部变量
 let amount =1;//第1个 let 
 let amount =100;//第2个 let 
 let amount =1000;//第3个 let 
 }
 return amount ;
 }
 console.log(calculateTotalAmount(true));

程序结果将会是0,因为块作用域中有了 let ,如果 amount=1 ,那么这个表达式将返回1。本例是一个演示,这里有一堆常量,它们互不影响,因为它们属于不同的块级作用域。
JavaScript 中的 var 只能声明一个变量,这个变量可以保存任何数据类型的值。ES6之前并没有定义声明常量的方式,ES6标准中引入了新的关键字 const 来定义常量。
使用 const 定义常量后,常量将无法改变, const 常量的用法说明如下。

1、const常量,只能一次赋值
const PI=3.14159;
PI=3.14;//报错 Assignment to constant variable.
2、对象常量

对象的属性可以修改,对象的引用不能修改

const obj={name:"kerr"};
obj.name="tom";
3、冻结对象

防止修改对象的属性

const obj=Object.freeze({name:"kerr"});
obj.name="tom";//报错,提示冻结对象不能再重新定义赋值

2.3模板字面量

2.3.1 Multi - line Strings (多行字符串)

ES 6的多行字符串是一个实用的功能,在ES 5中我们只能使用以下方法来表示多行字符串:

var roadPoem =, 江南好,风景旧曾谙。'
+,日出江花红胜火,1
+,春来江水绿如蓝。,
+,能不忆江南?'
+'忆江南-江南好1;

然而在ES 6中,仅仅用反引号就可以解决

var roadPoem = `江南好,风景旧曾谙。
日出江花红胜火,
春来江水绿如蓝。
能不忆江南?
2.3.2字符串占位符

使用模板和插入值是在字符串里输出变量的方式,在ES 5中开发者可以组合一个字符串

//在ES 6之前只能使用组合字符串的方式
var name = * your name is * + first + * ' +last + *.*;
var url=* http://localhost:3000/api/messages/* +id;

在ES 6 中,占位符是使用语法${NAME}的,将包含的NAME变量或者表达式放在反引号中

var name=`your name is ${first} ${last}. `;
var url=`http://localhost:3000/api/messages/${id}`;

2.4默认参数和rest参数

JavaScript定义默认参数的方式如下:

//JavaScript原先定义方式
var link=function (height,color,url){
var height =height || 50;
var color=color  | | * red*;
var url=url || 'http://baidu.com';
}

在ES 6中,可以直接把默认值放在函数申明中:

var link = function (height=50,color=* red*,url=`http://baidu.com *)

ES 6引入rest参数,用于获取函数的实参,不过rest参数不适合参数个数不确定的函数

ES 5中获取函数的实参:

function data(){
console.log(arguments);
}
data('pg','xj','jz');

在ES 6中,使用rest参数获取函数的实参:

function data(...args){
console.log(args);
}
data('苹果','香蕉','橘子');

rest参数必须放在参数最后的位置

function fn(a,b,...args){
console.log(a);
console.log(b);
console.log(args);
}
fn(100,200,300,400,500,600);

2.5解构赋值

house和mouse是key,同时也是hi变量

var data=$('body') . data();//data拥有两个属性house和mouse
house=data.house;
mouse=data.mouse;
//在Note.js中使用ES 5代码
var j sonMiddleware=require('bady-parser').j sonMiddleware;
var body=req.body;//body的两个属性,username和password
username = body.username;
password=body.password;

在ES 6中可以使用以下代码替换ES 5的代码

var { house,mouse)=$(1 body').data;
var (jsonMiddleware}=require('body-pareser');
var (username,password)=req.body;
//这个也同样适合数组
var [col1,col2]=$(' .cplumn*),[line1z line2,line3z,line5]=file.split(ln');

2.6展开运算符

第一个用途:组装数组

let color = ['red', 'yellow'];
let colorful = [...color, 'green', 'blue'];
console.log(colorful); // ["red", "yellow", "green", "blue"]

第二个用途:获取数组除了某几项的其他项

let num = [1, 3, 5, 7, 9];
let [first, second, ...rest] = num;
console.log(rest); // [5, 7, 9]

2.7增强的对象文本

2.7.1通过变量进行对象初始化
const
a=100,b=200,c=300;
obj={
	a
	b
	c
};
2.7.2简化定义对象方法
const lib={
	sum(a,b) { return a+b;},
	mult(a,b) {return a*b;}
};
console.log(lib.sum(100,200));//300
console.log(lib.mult(100,200));//20000

这里不能使用ES 6箭头函数(=>),因为该方法需要一个名称。如果直接命名每个方法,则可以使用=>箭头函数。例如:

const lib={
	sum:(a,b)=>a+b,
	mult:(a,b)=>a*b
};
console.log(lib.sum(100,200));//300
console.log(lib.mult(100,200));//20000
2.7.3动态属性键

通过在方括号[]内置表达式,可以在ES 6中到那个太分配对象键

const 
key1='one',
obj={
	[key1]:100,
	two:200,
	three:300
};
//表示obj.one=100,obj.two=200,obj.three=300
2.7.4解构属性中的变量

在ES 6中,通过解构可以创建于等效对象属性同名的变量。

const myObjecct={
	one:'洗衣机',
	two:'冰箱',
	three:'空调'
};
const{one,two,three}=myObject;
//表示	one='洗衣机',	two='冰箱',	three='空调'

2.8箭头函数

CoffecScript 就是因为有丰富的箭头函数,所以让很多开发者所喜爱。在ES6中,也有丰富的箭头出数。比如,以前我们使用闭包, this 总是预期之外地产生改变,而箭头函数的好处在于,现在 this 可以按照你的预期使用了,身处箭头函数里面, this 还是原来的 this 。
有了箭头函数,我们就不必像使用 that = this 或 self = this 、_ this = this 、 bind ( this )那么麻烦了。例如,下面的代码使用ES5就不是很优雅:

 var _this=this ;
$(*.btn *).click ( function (event){
this.ssenData();
})_

在ES6中则不需要使用_ this = this :

$ (*.btn*).click((event)=>{
this.sendData();
})

但并不是完全否定之前的方案,ES6委员会决定,以前的 function 的传递方式也是一个很好的方案,所以它们仍然保留了以前的功能。
下面是另一个例子,通过 call 传递文本给 logUpperCase ()函数,在ES5中:

 var logUpperCase = function (){
 var this = this ;
 this.string = this.string.toUpperCase ();
 return function (){
 return console.log (_this.string );
 }
 }
 logUpperCase .call({ string:*ES 6 rocks *});
 //而在Es6中并不需要用 this 浪费时间
 var logUpperCase = function (){
 this.string=this.string.toUpperCase ();
return()=>console.log(this.string);
}logUpperCase .call({string: * ES 6 rocks *})();

2.8Promise实现

在ES 6中有标准的Promise实现
下面是使用setTimeout()函数实现异步延迟加载函数;

setTimeout(function){
console.log('yay!*);
},1000);
var wait1000 = new Promise((resolve,reject)=>(
setTimeout(resolve,1000);
}).then(()=>(
console.log(* yay!*);
});

3、熟悉Vue.js的语法

3.1 v-bind

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
  <span v-bind:title="message">
    鼠标悬停几秒钟查看此处动态绑定的提示信息!
  </span>

    <!--1.导入Vue.js-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
    <script type="text/javascript">
        // 创建一个Vue实例
        var vm = new Vue({
            el:"#app",
            /*Model:数据*/
            data:{
                message:"mest Stduying vue "
            }
        });
    </script>
</div>
</body>
</html>

在这里插入图片描述
说明:

  • 看到的 v-bind attribute 被称为指令。指令带有前缀 v-,以表示它们是 Vue 提供的特殊 attribute
  • 它们会在渲染的 DOM 上应用特殊的响应式行为

3.2 v-if、v-else

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<!--Vue基本语法-->
<body>

<!--view层,模板-->
<div id="app">
<span v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span>
    <br>

    <!--v-if else-->
    <h1 v-if="type">yes</h1>
    <h2 v-else>No</h2>
    <h1 v-if="type==='A'">A</h1>
    <h1 v-else-if="type==='B'">B</h1>
    <h1 v-else="type==='C'">C</h1>

</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        data:{
        message:"你好 vue~",
            // type:true
            type:'A',
        counter :0,
        message:"mest Stduying vue "
        },
            methods: {//方法必须定义在Vue的method对象中
                sayHi:function (event) {
                    alert(this.message);
                }
    },

});
</script>

</body>
</html>

在这里插入图片描述
说明:

  • 在浏览器上运行,打开控制台
  • 在控制台输入vm.type=false然后回车,你会发现浏览器中显示的内容会直接变成NO
    注:使用v-*属性绑定数据是不需要双花括号包裹的

3.3 v-for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<!--Vue基本语法-->
<body>

<!--view层,模板-->
<div id="app">
<!--v-for-->
    <li v-for="item in items">
        {{item.message}}
    </li>


</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        data:{
        message:"你好 vue~",
            // type:true
            type:'A',
            items: [
                {message:'java-vue'},
                {message:'前端+后端'},
                {message:'java+mysql'}
            ],
        counter :0,
        message:"mest Stduying vue "
        },
            methods: {//方法必须定义在Vue的method对象中
                sayHi:function (event) {
                    alert(this.message);
                }
    },

});
</script>

</body>
</html>

在这里插入图片描述

3.4 v-on

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<!--Vue基本语法-->
<body>

<!--view层,模板-->
<div id="app">
<span v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span>
    <br>
<!--v-on    -->
<button v-on:click="sayHi">click me</button>
    <button v-on:click="counter +=1">add</button>
    <p>The button above has been clicked {{ counter }} times.</p>

</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        data:{
            // type:true
            type:'A',
        counter :0,
        message:"mest Stduying vue "
        },
            methods: {//方法必须定义在Vue的method对象中
                sayHi:function (event) {
                    alert(this.message);
                }
    },

});
</script>

</body>
</html>

在这里插入图片描述

3.5 v-html

该指令用于更新元素的innerHtml。内容按普通html插入。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>

<body>

<!--view层,模板-->
<div id="app">
    <!--    数据绑定-->
    <p v-html="message">古诗欣赏:</p>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        /*Model:数据*/
        data:{
            message:'<h3 style="color:red"> 老去惜花心已懒,爱梅犹绕江村。</h3>'
        }
    });
</script>

</body>
</html>

在这里插入图片描述

4、Vue 表单双向绑定

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<!--双向绑定 v-model-->
<body>

<!--view层,模板-->
<div id="app">
输入的是:<input type="text" v-model="message">{{message}}
    <br>
输入的是:<textarea type="text" v-model="message"></textarea>{{message}}

</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        data:
            {
                message:"123"
            }
    });
</script>

</body>
</html>

在这里插入图片描述
说明:
在文本区域插值 ({{text}}) 并不会生效,应用 v-model 来代替

复选框、多选框、下拉框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>

<body>

<!--view层,模板-->
<div id="app">

<!--Gender:-->
    <input type="radio" name="sex" value="Men" v-model="mest" >Men
    <input type="radio" name="sex" value="Female"  v-model="mest">Female
    <p>choose which:{{mest}}</p>
<br>
<!--    下拉框:-->
<select v-model="selected" >
    <option value="" disabled name="one">--请选择--</option>
    <option>A</option>
<!--    <option selected>B</option>-->
    <option >B</option>
    <option>C</option>
</select>
 <p>choose which:{{selected}}</p>
    <br>
<!--    复选框:-->

    <input type="checkbox" value="足球" v-model="check">
    <label>足球</label>
    <input type="checkbox" value="汽车" v-model="check">
    <label>汽车</label>
    <input type="checkbox" value="音乐" v-model="check">
    <label>音乐</label>
    <input type="checkbox" value="游戏" v-model="check">
    <label>游戏</label>
<p>choose which:{{check}}</p>



</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        // data:{
        //     mest:''
        // }
        // data:{
        //     selected:''
        // }
        data:{
            mest:'',
            selected:'',
            check:['足球']
        }
    });
</script>

</body>
</html>

在这里插入图片描述

组件:
组件是可复用的Vue实例, 说白了就是一组可以重复使用的模板, 跟JSTL的自定义标签、Thymeleal的th:fragment等框架有着异曲同工之妙,通常一个应用会以一棵嵌套的组件树的形式来组织

  • Vue.component():注册组件
  • cvzhanshi:自定义组件的名字
  • template:组件的模板

5、Axios异步通信

  • 从浏览器中创建XMLHttpRequests
  • 从node.js创建http请求
  • 支持Promise API[JS中链式编程]
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF(跨站请求伪造)

测试Axios

准备data数据

{
  "name": "qingjiang",
  "url": "https://www.baidu.com/",
  "page": 1,
  "isNonProfit": true,
  "address": {
    "street": "含光门",
    "city": "陕西西安",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://bilibili.com"
    },
    {
      "name": "mest",
      "url": "https://www.baidu.com/"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

测试:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<!--解决闪烁问题v-cloak-->
<div id="vue" v-cloak>
    <div>{{info.name}}</div>

    <div>{{info.address}}</div>

    <a v-bind:href="info.url">click me</a>

</div>
<body>
<!--引入js文件-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el:"#vue",
        //data()方法 data: 属性
        data(){
            return{
                //请求的返回参数合适,必须和json字符串一致
                info:{
                    name:null,
                    address:{
                        street:null,
                        city:null,
                        country:null
                    },
                    url:null
                }
            }
        },
        mounted(){//钩子函数
            axios.get('../data.json').then(response=>(this.info=response.data));
        }
    });
</script>
</body>
</html>

说明:

  • 在这里使用了v-bind将a:href的属性值与Vue实例中的数据进行绑定
  • 使用axios框架的get方法请求AJAX并自动将数据封装进了Vue实例的数据对象中
  • 我们在data中的数据结构必须和Ajax响应回来的数据格式匹配

Vue生命周期图
在这里插入图片描述

6、Vue 计算属性、内容分发、自定义事件

6.1 计算属性

计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>

<body>

<!--view层,模板-->
<div id="app">
<p>NowTime:{{currentTime1()}}</p>
<p>ComTime:{{currentTime2}}</p>


</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    // 创建一个Vue实例
    var vm = new Vue({
    el:"#app",
        data:{
        message:"hello mest"
        },
        methods:{
        currentTime1:function () {
        return Date.now();//返回一个时间戳
        }
        },
        // 计算属性:methods和computed方法不能重名
        computed:{
        currentTime2:function () {
            this.message;
        return Date.now();
        }
        }
    });
</script>

</body>
</html>

注意:methods和computed里的东西不能重名,重名之后,只会调用methods的方法

说明:

  • methods:定义方法, 调用方法使用currentTime1(), 需要带括号
  • computed:定义计算属性, 调用属性使用currentTime2,
    不需要带括号:this.message是为了能够让currentTime2观察到数据变化而变化
  • 如何在方法中的值发生了变化,则缓存就会刷新!可以在控制台使用vm.message=”你好呀",
    改变下数据的值,再次测试观察效果!

6.2 内容分发(插槽)

在Vue.js中我们使用元素作为承载分发内容的出口,可以称其为插槽,可以应用在组合组件的场景中。

需求:需要把下面的内容,让标题和内容通过插槽插入内容

<p>标题</p>
<ul>
    <li>abcd</li>
    <li>abcd</li>
    <li>abcd</li>
</ul>

定义一个代办事情的组件

 Vue.component('todo',{
        template:'<div>\
                <div>代办事项</div>\
                <ul>\
                    <li>cvzhanshi study Java</li>\
                </ul>\
            </div>'
    });

将上面的代码留出一个插槽,即slot

 Vue.component('todo',{
        template:'<div>\
                <slot"></slot>\
                <ul>\
                    <slot"></slot>\
                </ul>\
            </div>'
    });

定义一个名为todo-title的待办标题组件 和 todo-items的待办内容组件

Vue.component('todo-title',{
        props:['title'],
        template:'<div>{{title}}</div>'
    });
   
//这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
    Vue.component("todo-items",{
        props:["item","index"],
        template:"<li>{{index+1}},{{item}}</li>"
    });

slot通过name和组件绑定

 Vue.component('todo',{ var vm = new Vue({
        el:"#vue",
        data:{`在这里插入代码片`
            todoItems:['test1','test2','test3']
        }
    });

        template:'<div>\
                <slot name="todo-title"></slot>\
                <ul>\
                    <slot name="todo-items"></slot>\
                </ul>\
            </div>'
    });


实例化Vue并初始化数据

 var vm = new Vue({
        el:"#vue",
        data:{
            todoItems:['test1','test2','test3']
        }
    });

将数据通过插槽插入预留出来的位置

<todo>
        <todo-title slot="todo-title" v-bind:title="title"></todo-title>
        <todo-items slot="todo-items" v-for="item in todoItems" :item="item" ></todo-items>
    </todo>

说明:

  • ​ slot:是绑定组件用的
  • ​ :title --> 是v-bind:title的缩写

完整代码:

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <!--view层,模板-->
        <div id="vue">
            <todo>
                <todo-title slot="todo-title" v-bind:title="title"></todo-title>
                <!--<todo-items slot="todo-items" v-for="{item,index} in todoItems" v-bind:item="item"></todo-items>-->
                <!--如下为简写-->
                <todo-items slot="todo-items" v-for="item in todoItems" :item="item" ></todo-items>
            </todo>
        </div>
        <!--1.导入Vue.js-->
        <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
        <script type="text/javascript">
            Vue.component('todo',{
                template:'<div>\
			<slot name="todo-title"></slot>\
			<ul>\
			<slot name="todo-items"></slot>\
			 </ul>\
            </div>'
            });
            Vue.component('todo-title',{
                props:['title'],
                template:'<div>{{title}}</div>'
            });
            //这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
            Vue.component("todo-items",{
                props:["item"],
                template:"<li>{{item}}</li>"
            });
            var vm = new Vue({
                el:"#vue",
                data:{
                    title:"mest study vue",
                    todoItems:['test1','test2','test3']
                }
            });
        </script>
    </body>
</html>


7、小结

核心:数据驱动,组件化

优点:借鉴了AngularJS的模块化开发和React的虚拟Dom,虚拟Dom就是把Demo操作放到内存中执行;

常用的属性:
v-if
v-else-if
v-else
v-for
v-on绑定事件,简写@
v-model数据双向绑定
v-bind给组件绑定参数,简写:

组件化:
组合组件slot插槽
组件内部绑定事件需要使用到this.$emit(“事件名”,参数);
计算属性的特色,缓存计算数据


三、第一个vue-cli项目

3.1 Vue-cli简介

vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板
预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个估计项目就是脚手架,我们的开发更加的快速

3.2 环境配置

Node.js

下载地址: http://nodejs.cn/download/ 安装的时候一直下一步直到结束

确认是否安装成功: 在cmd中运行node -v命令,查看是否能够输出版本号 在cmd中运行npm -v命令,查看是否能够输出版本号
在这里插入图片描述

安装node.js淘宝镜像加速器(cnpm)

-g 就是全局安装
npm install cnpm -g

或使用如下语句解决npm速度慢的问题,但是每次install都需要 npm install
–registry=https://registry.npm.taobao.org

安装vue-cli

cnpm install vue-cli-g
#测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack
vue list

3.3 第一个vue-cli应用程序

创建一个基于webpack模板的vue应用程序

  1. 打开DOS系统窗口,进入到D盘

D:\Work\IdeaProjects-Vue\

  1. 创建一个名为myvue项目。

输入vue create mydemo 按下回车,
提示选择配置方式,包括Vue2.x默认配置、Vue3.0默认配置和手动配置,使用方向键选择Vue3.0(第二个),然后只需等待几秒加载。
提示:项目名称不能为大写,否则无法成功创建

  1. 项目创建成功后,在对应盘符可以看见项目文件夹,就可以启动项目。

使用"cd myvue"进入项目文件夹,然后使用脚手架提供的“npm run serve”命令启动。

在这里插入图片描述

  1. 如图,出现对应端口号后,可以去本地浏览器访问端口,localhost:8080即可。
    在这里插入图片描述
    提示:创建或加载过程中可能出现加载失败需要fix的情况,当出现问题时,它会给出提示,我们按照提示来就行。通过 npm audit fix来修复就行。极端情况:重新install,再重复以上操作。

四、webpack使用

WebPack是一款模块加载器兼打包工具, 它能把各种资源, 如JS、JSX、ES 6、SASS、LESS、图片等都作为模块来处理和使用

4.1 使用webpack

安装:

npm install webpack -g
npm install webpack-cli -g

测试安装成功:

webpack -v
webpack-cli -v

配置:

entry:入口文件, 指定Web Pack用哪个文件作为项目的入口
output:输出, 指定WebPack把处理完成的文件放置到指定路径
module:模块, 用于处理各种类型的文件
plugins:插件, 如:热更新、代码重用等
resolve:设置路径指向
watch:监听, 用于设置文件改动后直接打包

4.2 使用webpack

创建项目:
在这里插入图片描述

创建一个webpack文件夹,使用idea打开

  1. 创建一个名为modules的目录,用于放置JS模块等资源文件
  2. 在modules下创建模块文件hello.js
//暴露一个方法:sayHi
exports.sayHi = function(){
    document.write("<div>Hello Webpack</div>");
}

  1. 在modules下创建一个名为main.js的入口文件main.js,用于打包时设置entry属性
//require 导入一个模块,就可以调用这个模块中的方法了
var hello = require("./hello");
hello.sayHi();

  1. 在项目目录下创建webpack.config.js配置文件,使用webpack命令打包
module.exports = {
    entry:"./modules/main.js",
    output:{
        filename:"./js/bundle.js"
    }
}
  1. 打包:
    说明:打包如果失败,就用管理员权限运行webpack

在项目目录下创建HTML页面,如index.html,导入webpack打包后的JS文件

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>狂神说Java</title>
</head>
<body>
<script src="dist/js/bundle.js"></script>
</body>
</html>

直接运行index.html
在这里插入图片描述
提示:

参数–watch 用于监听变化,如果要打包的东西有变化,就重新打包
webpack --watch

五、vue-router路由

5.1 安装

基于第一个vue-cli进行测试学习; 先查看node modules中是否存在vue-router, vue-router是一个插件包, 所以我们还是需要用n pm/cn pm来进行安装的

npm install vue-router --save-dev

如果在一个模块化工程中使用它,必须要通过Vue.use()明确地安装路由功能

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter);

5.2 测试路由

  • 删除第一个vue-cli项目中的没用的东西
  • components 目录下存放我们自己编写的组件
  • 定义几个自己的组件 Content.vue 、Main.vue、mest.vue

Content.vue

<template>
    <div>
        <h1>内容页</h1>
    </div>
</template>

<script>
    export default {
        name:"Content"
    }
</script>

Main.vue

<template>
    <div>
        <h1>首页</h1>
    </div>
</template>

<script>
    export default {
        name:"Main"
    }
</script>

Mest.vue

<template>
    <div>
        <h1>Mest</h1>
    </div>
</template>

<script>
    export default {
        name:"Mest"
    }
</script>

  • 安装路由,在src目录下,新建一个文件夹:router,专门存放路由,配置路由index.js
import Vue from'vue';
//导入路由插件
import Router from 'vue-router';
//导入上面定义的组件
import Content from '../components/Content';
import Main from '../components/Main';
import Mest from "../components/Mest";
//安装路由
// Vue.use(Router) ;
createApp(App).use(router).mount('#app')
//配置路由
export default new Router({
    routes:[
        {
            //路由路径
            path:'/content',
            //路由名称
            name:'content',
            //跳转到组件
            component:Content
        },{
            //路由路径
            path:'/main',
            //路由名称
            name:'main',
            //跳转到组件
            component:Main
        }
        ,{
            //路由路径
            path:'/mest',
            //路由名称
            name:'main',
            //跳转到组件
            component:Mest
        }
    ]
});

  • 在main.js中配置路由
import Vue from 'vue';
import App from './App';

import router from './router';//自动扫描里面的路由配置
Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    components: { App },
    template: '<App/>'
})

  • 在App.vue中使用路由
<template>
  <div id="app">
    <!--
          router-link:默认会被渲染成一个<a>标签,to属性为指定链接
          router-view:用于渲染路由匹配到的组件
        -->
    <h1>cVzhanshi</h1>
    <router-link to="/main">首页</router-link>
    <router-link to="/content">内容</router-link>
    <router-link to="/mest">mest</router-link>
    <router-view></router-view>
  </div>
</template>

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

  • 运行npm run dev,然后浏览器访问localhost:8080

六、电影购票APP开发实战

6.1脚手架搭建

  • 选择好项目存放的目录,使用Vue脚手架创建一个项目,项目名称为:buyfilm。

vue create buyfilm

按照图示选择功能,选择路由器使用history模式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.2系统构架

本项目使用的都是本地静态资源,主要是前端展示。
其中public文件夹用来存放项目的静态文件。
在src中,放置了所有的源码文件。components用来放置比较小的的、公用的组件。
views用来放置三个主页面文件。
routers用来放置路由,其中index.js文件是主路由。
main.js是项目入口文件的JavaScript逻辑,在webpack打包之后将被注入到index.html页面中。
在这里插入图片描述

6.3项目运行效果:

通过运行 :npm run serve 后会展示出本地网址,打开链接就能访问本购票系统。
在这里插入图片描述
App主页面展示效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

6.4设计项目组件

6.4.1设计头部和底部导航组件

1、头部组件(Header)

<template>
    <header id="header">
        <h1>{{title}}</h1>
    </header>
</template>

<script>
    export default {
        name: "Header",
        // props是子组件访问父组件数据的唯一接口
        props:{
            title:{
                type:String,
                default:'风云电影'
            }
        }
    }
</script>
<!--scoped属性实现了私有化的样式-->
<style scoped>
    #header{
        width: 100%;
        height: 50px;
        color: #ffffff;
        background: #e54847;
        border-bottom:1px solid #e54847;
        position: relative;
    }
    #header h1{
        font-size: 18px;
        text-align: center;
        line-height: 50px;
        font-weight: normal;
    }
    #header i{
        position: absolute;
        left: 5px;top: 50%;
        margin-top: -13px;
        font-size: 26px;
    }
</style>

2、底部导航组件(TabBar)

<template>
    <div id="footer">
        <!--router-link>组件支持用户在具有路由功能的应用中单击导航。通过to属性指定目标地址,默认渲染为带有正确连接的<a>标签,可以通过配置tag属性生成别的标签。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的css类名-->
        <ul>
            <router-link tag="li" to="/movie">
                <i class="fa fa-film"></i>
                <p>电影</p>
            </router-link>
            <router-link tag="li" to="/cinema">
                <i class="fa fa-youtube-square"></i>
                <p>影院</p>
            </router-link>
            <router-link tag="li" to="/mine">
                <i class="fa fa-user-circle"></i>
                <p>我的</p>
            </router-link>
        </ul>
    </div>
</template>

<script>
    export default {
        name: "Tabbar"
    }
</script>

<style scoped>
    #footer{
        width: 100%;
        height: 50px;
        background: white;
        border-top: 2px solid #ebe8e3;
        position: fixed;
        left: 0;
        bottom: 0;
    }
    #footer ul{
        display: flex;
        text-align: center;
        height: 50px;
        align-items: center;
    }
    #footer ul li{
        flex: 1;
        height: 40px;
    }
    #footer li.active{color: #f03d37;}
    /* router-link-active:路由中自带的样式 选中时的颜色*/
    #footer li.router-link-active{color: #f03d37;}
    #footer ul i{font-size: 20px;}
    #footer ul p{
        font-size: 12px;
        line-height: 18px;
    }
</style>

6.4.2设计电影页面组件

1、城市组件(City)

<template>
    <div class="city_body">
        <div class="city_list">
            <div class="city_hot">
                <h2>热门城市</h2>
                <ul class="clearfix">
                    <li>北京</li>
                    <li>上海</li>
                    <li>天津</li>
                    <li>合肥</li>
                    <li>郑州</li>
                </ul>
            </div>
            <div class="city_sort">
                <div>
                    <h2>A</h2>
                    <ul>
                        <li>阿克苏</li>
                        <li>安康</li>
                        <li>安庆</li>
                    </ul>
                </div>
                <div>
                    <h2>B</h2>
                    <ul>
                        <li>白山</li>
                        <li>白城</li>
                        <li>宝鸡</li>
                    </ul>
                </div>
                <div>
                    <h2>C</h2>
                    <ul>
                        <li>沧州</li>
                        <li>长春</li>
                        <li>昌吉</li>
                    </ul>
                </div>
                <div>
                    <h2>D</h2>
                    <ul>
                        <li>大理</li>
                        <li>大连</li>
                        <li>大庆</li>
                    </ul>
                </div>
                <div>
                    <h2>E</h2>
                    <ul>
                        <li>鄂尔多斯</li>
                        <li>恩施</li>
                        <li>鄂州</li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="city_index">
            <ul>
                <li>A</li>
                <li>B</li>
                <li>C</li>
                <li>D</li>
                <li>E</li>
            </ul>
        </div>
    </div>
</template>
<script>
    export default {
        name: "City"
    }
</script>
<style scoped>
    #content .city_body{
        margin-top: 45px;
        display: flex;
        width: 100%;
        position: absolute;
        top: 0;
        bottom: 0;
    }
    .city_body .city_list{
        flex: 1;
        overflow: auto;
        background: #fff5f0;
    }
    .city_body .city_list::-webkit-scrollbar{
        background-color: transparent;
        width: 0;
    }
    .city_body .city_hot{
        margin-top: 20px;
    }
    .city_body .city_hot h2{
        padding-left: 15px;
        line-height: 30px;
        font-size: 14px;
        background: #f0f0f0;
        font-weight:normal;
    }
    .city_body .city_hot ul li{
        float: left;
        background: #fff;
        width: 29%;
        height: 33px;
        margin-top: 15px;
        margin-left: 3%;
        padding:0 4px;
        border: 1px solid #e6e6e6;
        border-radius: 3px;
        line-height: 33px;
        text-align: center;
        box-sizing: border-box;
    }
    .city_body .city_sort div{
        margin-top: 20px;
    }
    .city_body .city_sort h2{
        padding-left: 15px;
        line-height: 30px;
        font-size: 14px;
        background: #f0f0f0;
        font-weight: normal;
    }
    .city_body .city_sort ul{
        padding-left: 10px;
        margin-top: 10px;
    }
    .city_body .city_sort ul li{
        line-height: 30px;
    }
    .city_body .city_index{
        width: 20px;
        display: flex;
        flex-direction: column;
        justify-content: center;
        text-align: center;
        border-left:1px solid #e6e6e6;
    }
</style>

2、正在热映(NowPlaying)

<template>
    <div class="movie_body">
        <ul>
            <li>
                <div class="pic_show"><img src="../../../public/images/001.png" alt=""></div>
                <div class="info_list">
                    <h2>机械师2:复活</h2>
                    <p>观众评<span class="grade"> 8.9</span></p>
                    <p>主演: 杰森·斯坦森 杰西卡·阿尔芭 汤米·李·琼斯 杨紫琼 山姆·哈兹尔丁</p>
                    <p>今天50家影院放映800</p>
                </div>
                <div class="btn_mall">
                    购票
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/002.png" alt=""></div>
                <div class="info_list">
                    <h2>敢死队</h2>
                    <p>观众评<span class="grade"> 8.7</span></p>
                    <p>主演: 西尔维斯特·史泰龙,杰森·斯坦森,梅尔·吉布森</p>
                    <p>今天50家影院放映750</p>
                </div>
                <div class="btn_mall">
                    购票
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/003.png" alt=""></div>
                <div class="info_list">
                    <h2>最后的巫师猎人</h2>
                    <p>观众评<span class="grade"> 8.4</span></p>
                    <p>主演: 范·迪塞尔,萝斯·莱斯利,伊利亚·伍德,迈克尔·凯恩,丽纳·欧文</p>
                    <p>今天50家影院放映600</p>
                </div>
                <div class="btn_mall">
                    购票
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/004.png" alt=""></div>
                <div class="info_list">
                    <h2>饥饿游戏3</h2>
                    <p>观众评<span class="grade"> 7.6</span></p>
                    <p>主演: 詹妮弗·劳伦斯,乔什·哈切森,利亚姆·海姆斯沃斯</p>
                    <p>今天50家影院放映550</p>
                </div>
                <div class="btn_mall">
                    购票
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/005.png" alt=""></div>
                <div class="info_list">
                    <h2>钢铁骑士</h2>
                    <p>观众评<span class="grade"> 7.3</span></p>
                    <p>主演: 本·温切尔,乔什·布雷纳,玛丽亚·贝罗, 迈克·道尔, 安迪·加西亚</p>
                    <p>今天50家影院放映500</p>
                </div>
                <div class="btn_mall">
                    购票
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/006.png" alt=""></div>
                <div class="info_list">
                    <h2>奔跑者
                    </h2>
                    <p>观众评<span class="grade"> 6.6</span></p>
                    <p>主演: 尼古拉斯·凯奇,康妮·尼尔森,莎拉·保罗森,彼得·方达</p>
                    <p>今天50家影院放映500</p>
                </div>
                <div class="btn_mall">
                    购票
                </div>
            </li>
        </ul>
    </div>
</template>
<script>
    export default {
        name: "NowPlaying"
    }
</script>
<style scoped>
    #content .movie_body{
        flex: 1;overflow: auto;
    }
    .movie_body ul{
        margin: 0 12px;
        overflow: hidden;
    }
    .movie_body ul li{margin-top: 12px;display: flex;align-items: center;border-bottom: 1px solid #e6e6e6;padding-bottom: 10px;}
    .movie_body .pic_show{width: 64px;height: 90px;}
    .movie_body .pic_show img{width: 100%;}
    .movie_body .info_list{margin-left:10px;flex: 1;position: relative; }
    .movie_body .info_list h2{
        font-size: 17px; line-height: 24px;
        width: 150px;overflow: hidden;
        white-space: nowrap;
        text-overflow:ellipsis ;
    }
    .movie_body .info_list p{
        font-size:13px;
        color: #666;
        line-height: 22px;
        width: 200px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow:ellipsis ;
    }
    .movie_body .info_list .grade{
        font-weight: 700;
        color: #faaf00;
        font-size: 15px;
    }
    .movie_body .info_list img{
        width: 50px;
        position: absolute;
        right: 10px;
        top: 5px;
    }
    .movie_body .btn_mall, .movie_body .btn_pre{
        width: 47px;
        height: 27px;
        line-height: 28px;
        text-align: center;
        background-color: #f03d37;
        color: #fff;
        border-radius: 4px;
        font-size: 12px;
        cursor: pointer;

    }
    .movie_body .btn_pre{
        background-color: #3c9fe6;
    }
</style>

3、即将上映(ComingSoon)

<template>
    <div class="movie_body">
        <ul>
            <li>
                <div class="pic_show"><img src="../../../public/images/007.png" alt=""></div>
                <div class="info_list">
                    <h2>佐罗和麦克斯</h2>
                    <p><span class="person">46465</span>人想看</p>
                    <p>主演:格兰特·鲍尔 艾米·斯马特 博伊德·肯斯特纳</p>
                    <p>未来30天内上映</p>
                </div>
                <div class="btn_pre">
                    预售
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/008.png" alt=""></div>
                <div class="info_list">
                    <h2>废材特工</h2>
                    <p><span class="person">64645</span>人想看</p>
                    <p>主演: 杰西·艾森伯格,克里斯汀·斯图尔特,约翰·雷吉扎莫</p>
                    <p>未来30天内上映</p>
                </div>
                <div class="btn_pre">
                    预售
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/009.png" alt=""></div>
                <div class="info_list">
                    <h2>凤凰城遗忘录</h2>
                    <p><span class="person">42465</span>人想看</p>
                    <p>主演:Clint Jordan</p>
                    <p>未来30天内上映</p>
                </div>
                <div class="btn_pre">
                    预售
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/010.png" alt=""></div>
                <div class="info_list">
                    <h2>新灰姑娘</h2>
                    <p><span class="person">46465</span>人想看</p>
                    <p>主演: Cassandra Morris,Kristen Day</p>
                    <p>未来30天内上映</p>
                </div>
                <div class="btn_pre">
                    预售
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/011.png" alt=""></div>
                <div class="info_list">
                    <h2>鲨卷风4:四度觉醒</h2>
                    <p><span class="person">38465</span>人想看</p>
                    <p>主演: 塔拉·雷德,Ian Ziering,Masiela Lusha</p>
                    <p>未来30天内上映</p>
                </div>
                <div class="btn_pre">
                    预售
                </div>
            </li>
            <li>
                <div class="pic_show"><img src="../../../public/images/012.png" alt=""></div>
                <div class="info_list">
                    <h2>全境警戒</h2>
                    <p><span class="person">46465</span>人想看</p>
                    <p>主演: 戴夫·巴蒂斯塔,布兰特妮·斯诺,Angelic Zambrana</p>
                    <p>未来30天内上映</p>
                </div>
                <div class="btn_pre">
                    预售
                </div>
            </li>
        </ul>
    </div>
</template>

<script>
    export default {
        name: "ComingSoon"
    }
</script>

<style scoped>
    #content .movie_body{
        flex: 1;overflow: auto;
    }
    .movie_body ul{
        margin: 0 12px;
        overflow: hidden;
    }
    .movie_body ul li{margin-top: 12px;display: flex;align-items: center;border-bottom: 1px solid #e6e6e6;padding-bottom: 10px;}
    .movie_body .pic_show{width: 64px;height: 90px;}
    .movie_body .pic_show img{width: 100%;}
    .movie_body .info_list{margin-left:10px;flex: 1;position: relative; }
    .movie_body .info_list h2{
        font-size: 17px; line-height: 24px;
        width: 150px;overflow: hidden;
        white-space: nowrap;
        text-overflow:ellipsis ;
    }
    .movie_body .info_list p{
        font-size:13px;
        color: #666;
        line-height: 22px;
        width: 200px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow:ellipsis ;
    }
    .movie_body .info_list .grade{
        font-weight: 700;
        color: #faaf00;
        font-size: 15px;
    }
    .movie_body .info_list img{
        width: 50px;
        position: absolute;
        right: 10px;
        top: 5px;
    }
    .movie_body .btn_mall, .movie_body .btn_pre{
        width: 47px;
        height: 27px;
        line-height: 28px;
        text-align: center;
        background-color: #f03d37;
        color: #fff;
        border-radius: 4px;
        font-size: 12px;
        cursor: pointer;

    }
    .movie_body .btn_pre{
        background-color: #3c9fe6;
    }
</style>

4、搜索组件(Search)

<template>
    <div class="search_body">
        <div class="search_input">
            <div class="search_input_wrapper">
                <i class="fa fa-search"></i>
                <input type="text">
            </div>
        </div>
        <div class="search_result">
            <h3>电影/电视剧/综艺</h3>
            <ul>
                <li>
                    <div class="img"><img src="../../../public/images/001.png" alt=""></div>
                    <div class="info">
                        <p><span>机械师2 </span><span>8.9</span></p>
                        <p>剧情,喜剧,犯罪</p>
                        <p>2020-6-30</p>
                    </div>
                </li>
            </ul>
        </div>
    </div>
</template>
<script>
    export default {
        name: "Search"
    }
</script>
<style scoped>
    #content .search_body{
        flex: 1;
        overflow: auto;
    }
    .search_body .search_input{
        padding: 8px 10px;
        background-color: #f5f5f5;
        border-bottom: 1px solid #e5e5e5;
    }
    .search_body .search_input_wrapper{
        padding: 0 10px;
        border: 1px solid #e6e6e6;
        border-radius: 5px;
        background-color: #fff;
        display: flex;
    }
    .search_body .search_input_wrapper i{
        font-size: 16px;
        padding: 4px 0;
    }
    .search_body .search_input_wrapper input{
        border: none;
        font-size: 13px;
        color: #333;
        padding: 4px 0;
        outline: none;
    }
    .search_body .search_result h3{
        font-size: 15px;
        color: #999;
        padding: 9px 15px;
        border-bottom: 1px solid #e6e6e6;
    }
    .search_body .search_result li{
        border-bottom: 1px #c9c9c9 dashed;
        padding: 10px 15px;
        box-sizing: border-box;
        display: flex;
    }
    .search_body .search_result .img{
        width: 60px;
        float: left;
    }
    .search_body .search_result .img img{
        width: 100%;
    }
    .search_body .search_result .info{
        float: left;
        margin-left: 15px;
        flex: 1;
    }
    .search_body .search_result .info p{
        height: 22px;
        display: flex;
        line-height: 22px;
        font-size: 12px;
    }
    .search_body .search_result .info p:nth-of-type(1) span:nth-of-type(1){
        font-size: 18px;
        flex: 1;
    }
    .search_body .search_result .info p:nth-of-type(1) span:nth-of-type(2){
        font-size: 16px;
        color: #fc7103;
    }
</style>

6.4.3设计影院页面组件

影院列表组件(CiList)

<template>
    <div class="cinema_body">
        <ul>
            <li>
                <div>
                    <span>大地影院延庆金锣湾店</span>
                    <span class="q"><span class="price"> 38.5</span> 元起</span>
                </div>
                <div class="address">
                    <span>延庆区北街39号H座首层</span>
                    <span> >100km </span>
                </div>
                <div class="card">
                    <div>小吃</div>
                    <div>折扣卡</div>
                </div>
            </li>
            <li>
                <div>
                    <span>燕山影剧院</span>
                    <span class="q"><span class="price"> 37.5</span> 元起</span>
                </div>
                <div class="address">
                    <span>房山区燕山岗南路3</span>
                    <span> >120km</span>
                </div>
                <div class="card">
                    <div>小吃</div>
                    <div>折扣卡</div>
                </div>
            </li>
            <li>
                <div>
                    <span>万达影城昌平保利光魔店</span>
                    <span class="q"><span class="price"> 37.9</span> 元起</span>
                </div>
                <div class="address">
                    <span>昌平区鼓楼南街佳莲时代广场四层</span>
                    <span> >80km </span>
                </div>
                <div class="card">
                    <div>小吃</div>
                    <div>折扣卡</div>
                </div>
            </li>
            <li>
                <div>
                    <span>门头沟影剧院</span>
                    <span class="q"><span class="price"> 30.9</span> 元起</span>
                </div>
                <div class="address">
                    <span>门头沟区新桥大街12</span>
                    <span>  >110km </span>
                </div>
                <div class="card">
                    <div>小吃</div>
                    <div>折扣卡</div>
                </div>
            </li>
        </ul>
    </div>
</template>
<script>
    export default {
        name: "CiList"
    }
</script>
<style scoped>
    #content .cinema_body{
        flex: 1;
        overflow: auto;
    }
    .cinema_body ul{
        padding: 20px;
    }
    .cinema_body li{
        border-bottom: 1px solid #e6e6e6;
        margin-bottom: 20px;
    }
    .cinema_body div{
        margin-bottom: 10px;
    }
    .cinema_body .q{
        font-size: 11px;
        color: #f03d37;
    }
    .cinema_body .price{
        font-size: 18px;
    }
    .cinema_body .address{
        font-size: 13px;
        color:#666;
    }
    .cinema_body .address span:nth-of-type(2){
        float: right;
    }
    .cinema_body .card{
        display: flex;
    }
    .cinema_body .card div{
        padding: 0 3px;
        height: 15px;
        line-height: 15px;
        border-radius:2px;
        color: #f90;
        border:1px solid #f90;
    }
    .cinema_body .card div.or{
        color: #f90;
        border: 1px solid #f90;
    }
    .cinema_body .card div.bl{
        color: #589daf;
        border: 1px solid #589daf;
    }
</style>

6.4.4设计我的页面组件

只有一个登录/注册组件(未实现后端交互)

<template>
    <div class="login_body">
        <div>
            <input class="login_text" type="text" placeholder="账号/手机号/邮箱">
        </div>
        <div>
            <input class="login_text" type="password" placeholder="请输入您的密码">
        </div>
        <div class="login_btn">
            <input type="submit" value="登录">
        </div>
        <div class="login_link">
            <a href="#">立即注册</a>
            <a href="#">找回密码</a>
        </div>
    </div>
   
</template>

<script>
    export default {
        name: "Login"
    }
</script>

<style scoped>
    #content .login_body{
        width: 100%;
    }
    .login_body .login_text{
        width: 100%;
        height: 40px;
        border: none;
        border-bottom: 1px #ccc solid;
        margin:0 5px;
        outline: none;
    }
    .login_body .login_btn{
        height: 50px;
        margin: 10px;
    }
    .login_body .login_btn input{
        display: block;
        width: 100%;
        height: 100%;
        background: #e54847;
        border-radius: 3px;
        border: none;
        color: white;
    }
    .login_body .login_link{
        display: flex;
        justify-content: space-between;
    }
    .login_body .login_link a{
        text-decoration: none;
        margin: 0 5px;
        font-size: 12px;
        color:#e54847;
    }
</style>

6.5设计项目页面组件及路由配置

6.5.1电影页面组件及路由

<template>
    <div id="main">
        <!-- 头部组件-->
        <Header title="风云电影"></Header>
        <div id="content">
   
            <div class="movie_menu">
                <router-link tag="div" to="/movie/city" class="city_name">
                    <span>北京 </span><i class="fa fa-caret-down"></i>
                </router-link>
                <div class="hot_swtich">
                    <router-link tag="div" to="/movie/nowPlaying" class="hot_item active">正在热映</router-link>
                    <router-link tag="div" to="/movie/comingSoon" class="hot_item">即将上映</router-link>
                </div>
                <router-link tag="div" to="/movie/search" class="search_entry">
                    <i class="fa fa-search"></i>
                </router-link>
            </div>
            <!--二级路由渲染-->
            <keep-alive>
                <router-view></router-view>
            </keep-alive>

        </div>
        <!-- 尾部组件-->
        <TabBar></TabBar>
    </div>
</template>
<script>
    import Header from '../../components/Header';
    import TabBar from '../../components/TabBar';
    export default {
        name:'Movie',
        components:{
            Header,
            TabBar
        }
    }
</script>
<style scoped>
    #content .movie_menu{
        width: 100%;
        height: 45px;
        border-bottom: 1px solid #e6e6e6;
        display: flex;
        justify-content: space-between;
    }
    .movie_menu .city_name{
        margin-left: 20px;
        height: 100%;
        line-height: 45px;
    }
    .movie_menu .city_name.router-link-active{
        color: #ef4238;
        border-bottom: 2px solid #ef4238;
        box-sizing: border-box;
    }
    .movie_menu .hot_swtich{
        display: flex;
        height: 100%;
        line-height: 45px;
    }
    .movie_menu .hot_item{
        font-size: 15px;
        color: #666;
        width: 80px;
        text-align: center;
        margin: 0 12px;
        font-weight: 700;
    }
    .movie_menu .hot_item.router-link-active{
        color: #ef4238;
        border-bottom:2px solid #ef4238;
    }
    .movie_menu .search_entry{
        margin-right: 20px;
        height: 100%;
        line-height: 45px;
    }
    .movie_menu .search_entry.router-link-active{
        color: #ef4238;
        border-bottom:2px solid #ef4238;
        box-sizing: border-box;
    }
    .movie_menu .search_entry i{
        font-size: 24px;
        color: red;
    }
</style>

配置路由:

// movie路由
export default {
    path:'/movie',
    //按需载入的方式
    component:()=>import('../../views/Movie'),
    // 二级路由,使用children进行配置
    children:[
        {
            path:'city',
            component:()=>import('../../components/City')
        },
        {
            path:'nowPlaying',
            component:()=>import('../../components/NowPlaying')
        },
        {
            path:'comingSoon',
            component:()=>import('../../components/ComingSoon')
        },
        {
            path:'search',
            component:()=>import('../../components/Search')
        },
        // 重定向:当路径为/movie时,重定向到/movie/nowPlaying路径
        {
            path:'/movie',
            redirect:'/movie/nowPlaying'
        }
    ]
}

6.5.2影院页面组件及路由

<template>
    <div id="main">
        <Header title="风云影院"></Header>
        <div id="content">
            <div class="cinema_menu">
                <div class="city_switch">
                    全城 <i class="fa fa-caret-down"></i>
                </div>
                <div class="city_switch">
                    品牌 <i class="fa fa-caret-down"></i>
                </div>
                <div class="city_switch">
                    特色 <i class="fa fa-caret-down"></i>
                </div>
            </div>
            <CiList></CiList>
        </div>
        <TabBar></TabBar>
    </div>
</template>
<script>
    import Header from '../../components/Header';
    import TabBar from '../../components/TabBar';
    import CiList from '../../components/CiList';
    export default {
        name:'Cinema',
        components:{
            Header,
            TabBar,
            CiList
        }
    }
</script>
<style scoped>
#content .cinema_menu{
    width: 100%;
    height: 45px;
    border-bottom: 1px solid #e6e6e6;
    display: flex;
    justify-content: space-around;
    align-items: center;
    background: white;
}
</style>

配置路由:

// Cinema路由
export default {
    path:'/cinema',
    component:()=>import('../../views/Cinema')
}

6.5.3我的页面组件及路由

<template>
    <div id="main">
        <Header title="我的影院"></Header>
        <div id="content">
            <Login></Login>
        </div>
        <TabBar></TabBar>
    </div>
</template>
<script>
    import Header from '../../components/Header';
    import TabBar from '../../components/TabBar';
    import Login from '../../components/Login';
    export default {
        name:'Mine',
        components:{
            Header,
            TabBar,
            Login
        }
    }
</script>
<style scoped></style>

配置路由:

// mine路由
export default {
    path:'/mine',
    component:()=>import('../../views/Mine')
}

总结

百度文库源码提取链接:https://pan.baidu.com/s/1k_65SO6rIQxDaTe-So3lpw
提取码:点赞文章后私聊
参考文献:《Vue.js 3.0从入门到精通》清华大学出版社
文档参考:https://blog.csdn.net/qq_45408390/article/details/118151297
Vue中文文档:https://cn.vuejs.org/v2/guide/

  • 67
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值