常用前端框架
三大框架:vue (尤雨溪),react(facebook公司), angular(谷歌)
Vue框架介绍
Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。
vue框架前置知识点
html,css,js
了解Node、
npm(类似于java中的maven,管理依赖)
webpack
快捷使用vue操作
引入vue.js文件
下面是一个计数器小demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="utf-8">
</script>
<title>计数器</title>
</head>
<body>
<div id="app">
<button v-on:click="add()">+</button>
{{number}}
<button v-on:click="sub()">-</button>
</div>
</body>
<script>
new Vue({
el:"#app",
data:{
number:1
},
methods:{
add(){
if(this.number<10){
this.number++;
/* this.number=this.number+1; */
}
else{
alert("数字超过10,不能增加")
}
},
sub(){
if(this.number>0){
this.number--;
}
else{
alert("数字小于0,不能减少")
}
}
}
})
</script>
</html>
使用脚手架创建vue项目
步骤:
1.先安装vue/cli工具:npm install -g@vue/cli
2.切换到项目位置,打开cmd窗口,使用vue/cli去创建项目:vue create 项目名
创建好项目以后,按照cmd窗口上的提示运行服务
执行成功后,弹出如下窗口
在浏览器中输入地址,访问即可
Vue的项目结构
node_modules : 项目启动的依赖文件
public目录下:
index.html : vue项目首页的入口文件,将来vue文件中的标签代码,其实都被渲染到这个文件中,然后做展示
src目录 :src目录就是开发目录,基本上后面开发中做的事情,都在这个目录下
assets :将来放一些静态资源,比如图片资源等
components:用来存放一些被引用的组件文件
router:路由的配置文件,负责管理将来页面的跳转配置,在这个目录中的index.js中配置
views:存放一些使用的组件文件
app.vue : vue项目的入口vue组件,将来代码可以直接写在这个app.vue中,就能展示到页面上
main.js : 项目的核心配置文件,组织了App.vue文件被渲染到index.html的创建
main.js的作用,用来绑定渲染App.vue组件
//1,这里是es6的语法,表示vue实例选项对象的render方法,作为一个函数,接收h
//作为传入的参数,返回 h(App)
//2,vue在创建Vue实例,通过调用render方法来渲染实例的DOM树
//3,Vue对象在调用render方法的时候,会使用createElement函数作为参数
//然后createElement函数会以App,作为参数,进行调用,处理
//4,最后,Vue对象会将渲染好的结果,绑定到#app这个节点中,其实就是之前
//public目录中的index.html文件中
vue组件中,代码的编写方式
<template>
<div id="app">
<nav>
<h1>vue的项目</h1>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<!-- <router-view/> -->
<h2>{{message}}</h2>
<h3>{{name}}</h3>
<h3>{{age}}</h3>
<h2>{{user}}</h2>
<h3>{{user.username}}</h3>
<h3>{{user.age}}</h3>
<button @click="sayHello">点击</button>
</div>
</template>
<script>
export default{
data() {
return{
message : "hello,vue",
name: "jack",
age : 20,
user :{username:"tom",age:21}
}
},
methods:{
sayHello(){
alert("hello");
}
}
}
</script>
vue中常用指令
vue指令指的是 ,vue以v开头的一些命令属性
v-bind : 绑定事件的 ,可以简写成冒号 :
比如, <img v-bind:src = "xxxx"> 简写成 <img :src = "xxxx">
v-on :绑定事件的,简写成@
比如, <button v-on:click="触发函数名"> 简写成 <button @:click="触发函数名">
条件判断指令,控制元素的可见性,值是布尔值,true就是显示,false就是隐藏
v-if : 如果设为false,不渲染dom,这个元素就直接不存在
v-show:如果设为false,渲染dom,表示是将display设为none,元素本身还是存在的
<template>
<div id="app">
<nav>
<h1>vue的项目</h1>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<button @click="islogin">判断用户是否登录</button>
<p v-if="isLogin">你好,欢迎你登录 {{name}}</p>
<p v-show="false">你好,欢迎你2</p>
</div>
</template>
<script>
export default{
data() {
return{
name: "jack",
isLogin:false
}
},
methods:{
sayHello(){
alert("hello");
},
islogin(){
if(this.name != "" || this.name != null){
this.isLogin = true;
}else{
this.isLogin = false;
}
}
}
}
</script>
循环指令 v-for
v-for : 可以用来获取集合、数组中的数据,把数据单独展示
<template>
<div class="about">
<h1>This is an about page</h1>
<ul>
<li v-for="(fruit,index) in fruits" :key="index">
<p>水果编号:{{index+1}}-->水果名称:{{fruit}}</p>
</li>
</ul>
<table>
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
</tr>
<tr v-for="(s,i) in students" :key="i">
<td>{{i+1}}</td>
<td>{{s.name}}</td>
<td>{{s.age}}</td>
<td>{{s.gender}}</td>
</tr>
</table>
</div>
</template>
<script>
export default{
data() {
return{
fruits:["香蕉","苹果","梨子"],
students:[
{name:"jack",age:22,gender:"男"},
{name:"tom",age:21,gender:"男"},
{name:"lucy",age:20,gender:"女"}
]
}
}
}
</script>
Vue中的组件开发
将来开发大型页面的时候,如果将代码都写在一个页面中,代码会比较复杂
一般将来会用组件嵌套的方式开发项目
一般将来被别的组件引用的组件,都是放在components目录下
组件的编写 :
命名: 和写Java中的类名类似,推荐使用大写字母开头,大驼峰式的写法,防止和原html中的标签冲突
使用步骤 :
1,在components目录下新建一个vue文件
2,注册组件
3,引入组件
组件传值(重点)
1,父组件向子组件传递数据
2,子组件向父组件传递数据
3,非父子关系数据传递
父组件向子组件传递数据 :使用属性传递
1,编写父组件的代码
先注册使用子组件,在子组件中绑定自定义属性,并传递需要发送的数据
子组件向父组件传值 : 使用自定义的事件
子组件不能直接改变父组件的值,只能通过调用父组件的自定义事件来传值
$emit ,可以让父组件监听到自定义的事件
子组件Child.vue
<template>
<div>
<h1>这是child子组件</h1>
<button @click="sendData">点击传递数据</button>
</div>
</template>
<script>
export default{
data(){
return{
childData:"子组件的数据,可以传递到父组件中"
}
},
methods:{
sendData(){
this.$emit("childEvent",this.childData);
}
}
}
</script>
父组件App.vue
<template>
<div id="app">
<h1>这是App.vue组件</h1>
<Child @childEvent="changeDate"></Child>
来自子组件的数据:{{dataChild}}
</div>
</template>
<script>
import Child from "./components/Child.vue"
export default{
components:{
Child
},
data() {
return{
message:"父级的数据,传递到子级中",
dataChild:""
}
},
methods:{
changeDate(childData){
this.dataChild = childData;
}
}
}
</script>
购物车的计价案例
Carts.vue 购物车组件
Counter.vue 计数器组件
将来会在购物车中,引用计数器组件, Carts.vue是父组件 ,Counter.vue是子组件
Carts.vue
<template>
<div>
<h1>购物车</h1>
<ul>
<li v-for="(v,i) in fruits" :key="i">
{{v.name}} 单价: {{v.price}}
<Counter :count = "v.count" :index="i"
@sub="sub" @add="add"></Counter>
</li>
</ul>
<h1>总价格:</h1>
</div>
</template>
<script>
import Counter from "./Counter.vue"
export default{
components:{Counter},
data() {
return{
fruits:[
{name:"苹果",price:5.88,count:0},
{name:"香蕉",price:3.88,count:0},
{name:"例子",price:4.88,count:0}
]
}
},
methods:{
sub(index){
this.fruits[index].count--;
},
add(index){
this.fruits[index].count++;
}
}
}
</script>
Counter.vue
<template>
<div>
<button @click="sub">-</button>
{{count}}
<button @click="add">+</button>
</div>
</template>
<script>
export default{
props:["count","index"],
methods:{
sub(){
this.$emit("sub",this.index)
},
add(){
this.$emit("add",this.index)
}
}
}
</script>
非父子组件之间的传值,通过定义一个共享的js文件
购物车案例改进
增加一个清除所有功能,点击之后可以清除所有数据为0
app.vue
-----Control.vue 点击清除
-----Carts.vue
------Counter
store.js
export default{
state:{
fruits:[
{name:"苹果",price:5.88,count:0},
{name:"香蕉",price:3.88,count:0},
{name:"例子",price:4.88,count:0}
]
},
reset(){
this.state.fruits.map(v=>{
v.count = 0;
})
},
sub(i){
this.state.fruits[i].count--;
},
add(i){
this.state.fruits[i].count++;
}
}
Carts.vue
<template>
<div>
<h1>购物车</h1>
<ul>
<li v-for="(v,i) in soreData.fruits" :key="i">
{{v.name}} 单价: {{v.price}}
<Counter :count = "v.count"
:index="i"
@sub="sub"
@add="add"></Counter>
</li>
</ul>
<h1>总价格:{{totalPrice}}</h1>
</div>
</template>
<script>
import Counter from "./Counter.vue"
import store from "../store.js"
export default{
components:{Counter},
data() {
return{
soreData:store.state
}
},
methods:{
sub(index){
store.sub(index);
},
add(index){
store.add(index);
}
},
computed:{
totalPrice(){
let total = 0;
this.soreData.fruits.map(v=>{
total += v.price * v.count;
})
return total.toFixed(2);
}
}
}
</script>
<style>
</style>
Control.vue
<template>
<div>
<button @click="reset">重置数据</button>
</div>
</template>
<script>
import store from "../store.js"
export default{
methods:{
reset(){
store.reset();
}
}
}
</script>
<style>
</style>
App.vue
<template>
<div id="app">
<Control></Control>
<Carts></Carts>
</div>
</template>
<script>
import Carts from "./components/Carts.vue"
import Control from "./components/Control.vue"
export default{
components:{
Carts,
Control
}
}
</script>
计算属性和侦听器
计算属性 : computed
computed属性中和data属性一样,可以将定义的值、函数直接绑定在 插值表达式{{}}
将来如果某些值,需要通过计算才能获取的话,可以使用计算属性
侦听器 : watch
watch将来主要用来侦听某个属性的变化
<template>
<div id="app">
<!-- <Control></Control>
<Carts></Carts> -->
<!-- <Brother></Brother>
<Sister></Sister> -->
<h1>计算属性</h1>
<p>{{title}}</p>
<p>{{message}}</p>
<p>姓名:{{firstName + lastName}}</p>
<p>姓名:{{name}}</p>
<!-- 复杂的计算 总价 = 单价 * 数量 * 折扣 - 优惠券 -->
<p>单价 : {{price}}</p>
<p>数量: {{count}}
<button @click="sub">-</button>
<button @click="add">+</button>
</p>
<p>折扣:{{discount}}</p>
<p>总价:{{totalPrice}}</p>
</div>
</template>
<script>
// import Carts from "./components/Carts.vue"
// import Control from "./components/Control.vue"
// import Brother from "./components/Brother.vue"
// import Sister from "./components/Sister.vue"
export default{
components:{
// Carts,
// Control
// Brother,
// Sister
},
data() {
return{
title:"hello",
firstName:"张",
lastName:"三",
price:999,
count:0,
discount:0.5,
totalPrice:0
}
},
computed:{
message(){
return "hello,computed"
},
name(){
return this.firstName + this.lastName
},
// totalPrice(){
// return this.price * this.count * this.discount
// }
},
methods:{
add(){this.count++},
sub(){this.count--}
},
watch:{
count(val){
console.log(val);
this.totalPrice = this.price * val * this.discount;
}
}
}
</script>
computed和watch比较 :
将来如果需要观察,某个值发生改变,影响多个值,可以使用watch(观察一个值)
如果多个值发生改变,为了得到一个结果,使用computed
实际开发中,使用computed较多
生命周期钩子
每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。
每个生命周期钩子就是一个函数
vue中的表单
v-model 表单数据的双向绑定
<template>
<div id="app">
<h1>{{username}}</h1>
<h1>{{password}}</h1>
用户名:<input type="text" v-model="username" > <br>
密码:<input type="text" v-model="password" >
<button @click="submit">提交</button>
<button @click="bind">绑定数据到输入框</button>
</div>
</template>
<script>
export default{
data() {
return{
username : "",
password: ""
}
},
methods:{
submit(){
console.log(this.username + "--" + this.password)
},
bind(){
this.username = "tom";
this.password = "123";
}
}
}
</script>
复杂表单提交(重点)
<template>
<div id="app">
<form @submit.prevent="postData">
<div>
用户名: <input type="text" v-model="formData.username">
</div>
<div>
密码: <input type="text" v-model="formData.password">
</div>
<div>
爱好:
<select v-model="formData.hobby">
<option value="game">游戏</option>
<option value="study">学习</option>
</select>
</div>
<div>
性别:
男 <input type="radio" value="男" v-model="formData.gender">
女 <input type="radio" value="女" v-model="formData.gender">
</div>
<div>
课程:
数学 <input type="checkbox" value="数学" v-model="formData.course">
语文 <input type="checkbox" value="语文" v-model="formData.course">
英语 <input type="checkbox" value="英语" v-model="formData.course">
</div>
<button>提交</button>
</form>
</div>
</template>
<script>
export default{
data() {
return{
formData:{
username:"",
password:"",
hobby:"",
gender:"",
course:[]
}
}
},
methods:{
postData(){
console.log(this.formData)
}
}
}
</script>
路由
路由主要用来控制页面跳转,以及数据的访问的
路由配置过程:
1.先创建页面
2.在router文件夹下的index.js下面添加路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Home from'../views/Home.vue'
import Blog from '../views/Blog.vue'
import Video from '../views/Video.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/home',
name: 'home',
component: Home
},
{
path: '/blog',
name: 'blog',
component: Blog
},
{
path: '/video',
name: 'video',
component: Video
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
在页面添加跳转路径
<div id="nav">
<router-link to="/home">首页</router-link>||
<router-link to="/blog">博客</router-link>||
<router-link to="/video">视频</router-link>||
<button @click="jump">跳转到博客</button>
</div>
<router-view ></router-view>
<!-- router-view用来渲染上面配置的路由跳转,不加的话路由跳转不起作用-->
展示效果如下:
给按钮添加跳转,绑定对应的跳转方法
methods:{
jump(){
this.$router.push("/blog");/* router一般用来跳转地址,route用来传递数据 */
}
}
关于router和 route的区别:
this.$router.push("/blog"); 自己定义跳转页面的页面,一般用来写在执行某个操作完成后,跳转页面
this.$route 实现数据传递