文章目录
02 Vue进阶(一)
一、Vue实例
1、一个基本的实例
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
{{title}} <br/>
<button type="button" @click="toUpperCase">点我变大写</button>
<hr>
小写:{{toLowerCase}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
title:'Hello VUE'
},
methods:{
toUpperCase:function () {
this.title = this.title.toUpperCase();
}
},
computed:{
toLowerCase:function () {
return this.title.toLowerCase();
}
},
watch:{
title:function (n,o) {
console.log(n+":"+o);
}
}
});
</script>
</html>
2、新的实例
在一个实例中,通过调用另一个实例的属性,来操作其属性
var v2 = new Vue({
el:"app2",
data:{},
methods:{
changeTitle:function () {
v1.title = "Hello Java";
}
}
});
3、一个实例改变另一个实例中的内容,通过给实例命名
<div id="app2">
<button type="button" @click="changeTitle">点击我改变v1的title</button>
</div>
4、在vue外面操作vue实例——操作属性
5、调用vue实例中的方法——操作方法
var v2 = new Vue({
el:"#app2",
data:{},
methods:{
changeTitle:function () {
v1.title = "Hello Java"; //操作属性
},
useV1Method:function () {
v1.toUpperCase(); //操作方法
}
}
});
6、Vue的实例属性
常用的实例属性:
- vm.$data:获取属性;
- vm.$el:获取实例挂载的元素;
- vm.$options:获取自定义选项/属性/函数;
- vm.$refs:获取通过ref属性注册的DOM对象;
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>05_InstanceProperties</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div>
<h1>{{msg}}</h1>
<h2 ref='hello'>Hello</h2>
<h2 ref='vue'>Vue</h2>
</div>
</body>
<script>
let vm = new Vue({
el : 'div',
data : {
msg : 'sikiedu'
},
username : 'joey',
password : '123',
login(){
console.log("login");
}
});
/*$.data*/
console.log(vm.$data.msg);
console.log(vm.msg);
/*$el*/
console.log(vm.$el);
vm.$el.style.color = 'red';
/*$options*/
console.log(vm.$options.username);
console.log(vm.$options.password);
vm.$options.login();
/*$refs*/
console.log(vm.$refs);
vm.$refs.hello.style.backgroundColor = 'yellow';
</script>
</html>
https://blog.csdn.net/qq_40323256/article/details/100857233
7、实例属性ref的用法:相当于是id
<button ref="mybtn1" id="btn" type="button" @click="btnclick">点我</button>
<button ref="mybtn2" id="btn" type="button" @click="btnclick">点我</button>
methods:{
btnclick:function () {
this.$refs.mybtn1.innerHTML = "thhhhhhhhhhhhhhhhhhhh";
}
}
ref的使用:
在vue 里面,往往使用ref属性来代替id属性的使用。那么就可以快速的通过调用ref的值来获得页面中的某个元素
8、动态绑定vue实例到页面中
<div id="app">
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var v1 = new Vue({
template:"<h1>Hello</h1>"
});
v1.$mount("#app");
</script>
</html>
$mount的使用:
实现了页面的元素和vue对象的动态绑定,之前都是通过el的方式来绑定,也可以通过moount实例属性进行绑定
二、Vue组件
Vue的一大特性就是:组件化
即:可以将Vue对象作为一个组件,被反复使用
要想实现组件化,需要在页面注册组件:关于注册的方式有两种:
- 全局注册
- 本地注册
1、注册组件(全局注册)
Vue.component("组件名",{Vue对象});
使用组件:
在Vue绑定了的HTML中才能可以使用组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue组件</title>
</head>
<body>
<div id="app">
<model1></model1>
</div>
<div id="app2">
<model1></model1>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
<!--全局注册 -->
Vue.component("model1",{
template:"<div>{{title}} <button type='button' @click='btnfn'>点我</button></div>",
data:function () {
return{
title:"China"
}
},
methods:{
btnfn:function () {
alert("hello")
}
}
});
new Vue({
el:"#app"
});
new Vue({
el:"#app2"
});
</script>
</html>
只有div 被Vue绑定再能使用Vue的组件
2、作为组件的Vue对象的特点
Vue.component("组件名",{Vue对象});
这个Vue对象和之前的Vue对象有区别:
1)特点一:data
以前:
new Vue({
el:"#app",
data:{
title:"CHina"
},
methods:{
}
});
现在:
data:function () {
return{
title:"China"
}
}
2)特点2:template写法
template是将内容展现在页面上的一个键,一定要注意的一点:
template里必须有写只能有一个根元素
错误写法:
template:"<h1>{{title}}</h1> <button type='button' @click='btnfn'>点我</button>",
正确写法:
template:"<div>{{title}} <button type='button' @click='btnfn'>点我</button></div>",
3、Vue组件的本地(局部)注册
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue组件之本地(局部)注册</title>
</head>
<body>
<div id="app">
<mymodel></mymodel>
</div>
<div id="app2">
<!--本地注册找不到-->
<mymodel></mymodel>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
/*本地注册*/
var model1 = {
template:"<div>{{title}} <button type='button' @click='btnfn'>点我</button></div>",
data:function () {
return{
title:"China"
}
},
methods:{
btnfn:function () {
alert("hello")
}
}
}
new Vue({
el:"#app",
components:{
"mymodel":model1
}
});
</script>
</html>
三、Vue实例的生命周期
一个Vue对象会经历:初始化、创建、绑定、更新、销毁等阶段,每个阶段都会有相应的生命周期钩子函数
四、Vue结合BootStrap搭建首页
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
<style>
.product{
width: 300px;
height: 400px;
border: 1px solid black;
display: inline-block;
margin-top: 20px;
margin-left: 60px;
margin: 20px;
overflow: hidden;
}
</style>
</head>
<body>
<div id="app" class="container">
<!--导航-->
<div>
<ul class="nav nav-pills">
<li v-for="nav in navigateData" role="presentation"><a href="#">{{nav}}</a></li>
</ul>
</div>
<!--轮播图-->
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li v-for="(myImg,i) in banner_imgs" :key="i"
data-target="#carousel-example-generic" data-slide-to="i" :class="i==0 ? 'active':''" ></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div v-for="(myImg,i) in banner_imgs" :key="i" :class="i==0 ? 'active':''" class="item">
<img style="width: 100%;height: 300px;" :src="myImg" alt="你的图挂了">
<div class="carousel-caption">
...
</div>
</div>
</div>
<!-- Controls -->
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<!--商品列表-->
<div>
<!--第一行的商品-->
<div>
<div v-for="product in products" class="product">
<img :src="product.pimg" alt="">
<p>{{product.pname}}</p>
<p>{{product.pprice}}</p>
</div>
</div>
</div>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
navigateData:['首页','最新商品','搜索','购物车','我的订单'],
banner_imgs:["static/img/1.jpeg","static/img/2.jpeg","static/img/3.jpeg"],
products:[
{
pname:'华为 HUAWEI Mate 40 Pro',
pimg:'static/img/华为 HUAWEI Mate 40 Pro.jpg',
pprice:6999
},
{
pname:'华为 HUAWEI nova 8 Pro',
pimg:'static/img/华为 HUAWEI nova 8 Pro.jpg',
pprice:3999
},
{
pname:'华为Mate X2/MateX2新款折叠屏手机5G',
pimg:'static/img/华为MateX2.jpg',
pprice:6999
}
]
}
});
</script>
</body>
</html>
大致效果:
五、vue的开发模式
1、vue-cli脚手架工具
vue-cli相当于我们后端使用maven创建项目,使用maven创建项目有两个目的:一是通过maven的依赖机制,能够
快速的管理依赖;二是通过maven来确定项目的结构,所谓项目的结构就是项目里有哪些文件和文件夹,文件夹是
一个怎样的层级关系
问题:一个Vue项目的项目结构到底是怎样的?我们能不能快速获得这样的项目结构呢?
解决:可以通过vue-cli脚手架工具解决,vue-cli里放了很多常用的项目骨架,直接拿来用就可以搭建出一个拥有比较成熟的项目结构的项目
1.1 vue-cli的使用
1.1.1 安装node.js
要想使用vue-cli得先安装node.js
node.js就是一个可以让前端运行在node.js提供的服务器上的一个工具,换句话说,就是提供一个服务器,官网下载即可
首先下载node.js https://nodejs.org/zh-cn/download/
测试是否安装成功:
node -v
v12.18.2
1.1.2 使用node.js安装vue-cli
npm install vue-cli -g
或
cnpm install vue-cli -g
检查是否安装成功:
vue --version
2.9.6
npm -v
6.14.5
淘宝镜像加速(cnpm):
#全局安装 -g
npm install cnpm -g
#或使用如下语句解决npm速度慢的问题
npm install -g cnpm --registry=https://registry.npm.taobao.org
之后使用npm命令时就可以替换成cnpm
- 使用vue list命令查看当前可用的vue骨架
2、使用vue-cli下载项目骨架搭建我们的项目
2.1 创建一个目录
C:\Users\17316\Desktop\终级文档\1、笔记\1.20VUE\code\myCode
2.1 创建一个基于webpack-simple模板的vue程序
2.1.1 下载项目骨架
-
使用vue命令创建基于
vue-webpack-simple
骨架的项目,vue-cli-demo
是项目名,过程中需要输入一些参数,回车是使用提示的值
#vue-cli-demo:项目名
vue init webpack-simple myvuedemo
使用命令后当前路径下就会生成一个myvuedemo的文件夹,里面存放着webpack-simple骨架应该有的文件(下载过来的)
2.1.2 安装项目依赖
npm install
多出个文件夹:node_modules
2.1.3 使用开发模式运行项目
npm run dev
访问:http://localhost:8080/
2.2 创建一个基于webpack模板的vue程序
出现的问题:
vue-cli · Failed to download repo vuejs-templates/webpack: connect ETIMEDOUT xxx.xxx.xxx.xxx:443
解决办法:
https://blog.csdn.net/weixin_42418774/article/details/107316463
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c6VT0eyI-1616466496924)(https://gitee.com/lisa_dehui/MyImages/raw/master/img/20210321160759.png)]
#离线初始化
vue init webpack myvuedemo --offline
项目构建成功:
To get started:
1.cd myvuedemo #进入myvuedemo
2.npm install (or if using yarn: yarn) #会根据package.json里面的文件下载依赖
3.npm run dev #启动该项目
可以使用IDEA open该项目
运行:
npm run dev
访问:localhost:8080
成功!
3、认识webpack模板
webpack是一款模块加载器兼打包工具,它能把各种资源如,JS、JSX、ES6、SASS、LESS、图片等都作为模块来处理和使用
- 安装:
npm install webpack -g
npm install webpack-cli -g
测试安装成功:
webpack -v
webpack-cli -v
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Si4r4fLN-1616466496930)(https://gitee.com/lisa_dehui/MyImages/raw/master/img/20210322155715.png)]
3.1 项目内的结构
1)package.json :具体的依赖信息
我们安装的是最新的,这里不是最新的,后面有可能打包失败,就要修改这里
2)webpack.config.js 配置文件
创建webpack.config.js
配置文件
3.2 使用webpack
1.创建项目
用IDEA打开该文件夹
2.创建一个名为modules的目录,用于放置JS模块等资源
3.在modules下创建模块文件,如hello.js,用于编写JS代码
//暴露一个方法
exports.sayHi = function () {
document.write("<h1>Webpack学习</h1>");
};
4.在modules下创建一个main.js的入口文件,用于打包时设置entry属性
//引入js:当暴露多个方法时,只引入一次
//require()导入一个模块,就可以调用这个模块中的方法了
var hello = require("./hello");
//调用
hello.sayHi();
hello.sayHi2();
5.在项目目录下创建一个webpack.config.js配置文件,使用webpack命令打包
//打包
module.exports = {
entry:'./modules/main.js',/*入口*/
output:{
filename:"./js/bundle.js" /*输出的位置文件*/
}
};
webpack命令打包:
把我们写的ES6的语法打包压缩成ES5
6.在项目目录下创建index.html,导入打包文件,并访问
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="dist/js/bundle.js">
</script>
</body>
</html>
访问:
说明:
#参数 --watch 用于监听变化
webpack --watch
4、认识webpack-simple
1)index.html
无论前端页面多么复杂,index.html 都只有11行
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>myvuedemo</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
实际的内容已经打包进 /dist/build.js
2)main.js文件是整个文件的入口
import Vue from 'vue'
// 导入了 APP.vue 组件
import App from './App.vue'
new Vue({
// 让当前 vue 对象绑定页面上的id是app的那个div
el: '#app',
// 让 App.vue 的内容展现在该 div 中
render: h => h(App)
})
3)App.vue
App.vue 这种以“.vue”为扩展名的文件,实际上就是一个 Vue 对象,这种文件,也称为 Vue 组件。
六、Vue文件的组成部分
1.让IDEA支持Vue插件
2.Vue文件的组成部分
<!-- 表示HTML :template 必须有一个根节点。-->
<template>
<div>
</div>
</template>
<!-- 表示JS -->
<script>
<!-- 暴露一个默认 Vue 对象 -->
export default {
// 对象名
name: 'app',
// 数据部分
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
// 方法部分
methods:{},
// 计算属性部分
computed:{},
// 监听部分
watch:{}
}
</script>
<!-- 表示CSS -->
<style scoped>
</style>
3.在vue组件中使用多个vue组件搭建一个页面
创建组件:
3.1 Header.vue
<template>
<div>
<h1> {{title}}</h1>
</div>
</template>
<script>
export default {
name: "Header",
data() {
return{
title:'二手用品分享网站'
}
}
}
</script>
<style scoped>
</style>
3.2 content.vue
<template>
<div>
商品列表。。
</div>
</template>
<script>
export default {
name: "content"
}
</script>
<style scoped>
</style>
3.3 bottom.vue
<template>
<div>
lisa版权所有!!!
</div>
</template>
<script>
export default {
name: "bottom"
}
</script>
<style scoped>
</style>
3.4 在main.js里面全局注册
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App' /*导入当前路径下的App.vue*/
import Header from './components/Header'
import Content from './components/content'
import Bottom from './components/bottom'
/*全局注册三个组件===》可以把组件拿来当标签一样使用*/
Vue.component({
'MyHeader':Header,
'MyContent':Content,
'myBottom':Bottom
});
/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App)
})
3.5 在App.vue 中使用组件
<template>
<div id="app">
<img src="./assets/logo.png">
<HelloWorld/>
<MyHeader>
</MyHeader>
<MyContent>
</MyContent>
<MyBottom>
</MyBottom>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3.6 重新运行并访问
npm run dev
3.7 说明
1 项目中组件的全局注册
在 main.js 中,通过 import 和 Vue.component配合,来将一个 vue 文件注册成一个标签。该标签就可以在整个项目中使用。
2 在app.vue中本地注册这些组件并使用
在组件内部去注册另外一个组件,成为一个标签,这个标签只在组件内部使用,而不能在其他组件内使用。
<template>
<div id="app">
<img src="./assets/logo.png">
<HelloWorld/>
<MyHeader>
</MyHeader>
<MyContent>
</MyContent>
<MyBottom>
</MyBottom>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import Header from './components/Header'
import Content from './components/content'
import Bottom from './components/bottom'
export default {
name: 'App',
//本地注册
components: {
HelloWorld,
'MyHeader':Header,
'MyContent':Content,
'MyBottom':Bottom
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
七、各组件中的参数传递
1、父传子
通过子组件的props部分,来指明可以 接受的参数,父组件通过在标签中写明参数的键值来传递参数
props 是表示一个组件的参数部分,props 的写法有两种:
- 通过数组来定义
props:['myprop1','myprop2'...]
- 通过对象来定义
props:{
myName:{
type:String,
required:true,
default:'默认值'
}
}
2、子传父
content.vue
<template>
<div>
商品列表。。
{{MyTitle}}
<hr>
<button type="button" @click="btnfn('hello BeiJing')">点我</button>
</div>
</template>
<script>
export default {
name: "content",
/*方式一:*/
/*props:['MyTitle']*/
/*方式二:*/
props:{
'MyTitle':{
type:String,
required:true,
default:'XXX'
},
btnfn:{
type: Function
}
}
}
</script>
<style scoped>
</style>
App.vue
<template>
<div id="app">
<img src="./assets/logo.png">
<HelloWorld/>
<MyContent :MyTitle="msg" :btnfn="FBtn">
</MyContent>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import Header from './components/Header'
import Content from './components/content'
import Bottom from './components/bottom'
export default {
name: 'App',
data(){
return{
msg:'Hello China!!!!!'
}
},
methods:{
FBtn:function (m) {
this.msg = m;
}
},
components: {
HelloWorld,
'MyHeader':Header,
'MyContent':Content,
'MyBottom':Bottom
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3、以事件发射的方式实现子传父
在子组件中,使用 this.$emit("键","值")
在父组件中,子组件的标签中,使用@键="msg=$event"
, 其中$event就能得到值,msg是父组件中 vue 属性。
content.vue
<template>
<div>
商品列表...
{{myTitle}}
<button type="button" @click="doclick">点我</button>
</div>
</template>
<script>
export default {
name: "content",
/* 第一种写法,通过数组来定义 */
// props:['myTitle']
/* 第二种写法,通过对象来定义 */
props: {
myTitle: {
type: String,
required: true,
default: "没传参数"
},
btnfn:{
type: Function
// FCfn(m) {
// this.msg = m
// }
}
},
methods:{
doclick(){
this.$emit('newName','子组件内容')
}
}
}
</script>
<style scoped>
</style>
App.vue
<template>
<div id="app">
<!-- 给子组件传值 -->
<MyContent :myTitle="msg" @newName="msg=$event"></MyContent>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
msg: '父组件传给子组件!!!'
}
},
methods: {
FCfn(m) {
this.msg = m
}
}
}
</script>
<style>
</style>
center;
color: #2c3e50;
margin-top: 60px;
}
### 3、以事件发射的方式实现子传父
在子组件中,使用 `this.$emit("键","值")`
在父组件中,子组件的标签中,使用` @键="msg=$event"`, 其中$event就能得到值,msg是父组件中 vue 属性。
content.vue
```javascript
<template>
<div>
商品列表...
{{myTitle}}
<button type="button" @click="doclick">点我</button>
</div>
</template>
<script>
export default {
name: "content",
/* 第一种写法,通过数组来定义 */
// props:['myTitle']
/* 第二种写法,通过对象来定义 */
props: {
myTitle: {
type: String,
required: true,
default: "没传参数"
},
btnfn:{
type: Function
// FCfn(m) {
// this.msg = m
// }
}
},
methods:{
doclick(){
this.$emit('newName','子组件内容')
}
}
}
</script>
<style scoped>
</style>
App.vue
<template>
<div id="app">
<!-- 给子组件传值 -->
<MyContent :myTitle="msg" @newName="msg=$event"></MyContent>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
msg: '父组件传给子组件!!!'
}
},
methods: {
FCfn(m) {
this.msg = m
}
}
}
</script>
<style>
</style>