学习vue需要了解的知识
NPM 使用介绍
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
NodeJs介绍
简单的说 Node.js 就是运行在服务端的 JavaScript。
Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
**优点:**1. 高并发(最重要的优点)
\2. 适合I/O密集型应用
**缺点:**1. 不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;
解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;
\2. 只支持单核CPU,不能充分利用CPU
\3. 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃
原因:单进程,单线程
解决方案:(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
(2)开多个进程监听同一个端口,使用cluster模块;
\4. 开源组件库质量参差不齐,更新快,向下不兼容
\5. Debug不方便,错误没有stack trace
vue
Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架。
Vue 只关注视图层, 采用自底向上增量开发的设计。
Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
Vue 学习起来非常简单,本教程基于 Vue 2.1.8 版本测试。
第一个案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--获取属性值-->
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
</body>
</html>
vue安装
1:独立版本
我们可以在 Vue.js 的官网上直接下载 vue.min.js 并用 标签引入
2:cdn安装
-
Staticfile CDN(国内) : cdn.staticfile.org/vue/2.2.2/v…
-
unpkg:unpkg.com/vue/dist/vu…, 会保持和 npm 发布的最新的版本一致。
3:npm安装
1:下载node.js
直接点击下一步傻瓜式安装
2:配置环境变量
置环境变量 让path指向 node.js的安装目录的node.exe文件
如:
PATH=D:/node_home/node.exe
3:查看安装版本
安装完了node.js已经自带了npm这时候可以查看node.js和npm的版本
C:\Users\admin>node -v
v12.18.4
C:\Users\admin>npm -v
6.14.6
C:\Users\admin>
4:npm修改镜像
修改镜像比较麻烦,这里安装一个切换镜像工具 nrm
安装语法是npm install nrm
npm install nrm
5:查看可用的镜像
C:\WINDOWS\system32>nrm ls
npm -------- https://registry.npmjs.org/
yarn ------- https://registry.yarnpkg.com/
cnpm ------- http://r.cnpmjs.org/
* taobao ----- https://registry.npm.taobao.org/
nj --------- https://registry.nodejitsu.com/
npmMirror -- https://skimdb.npmjs.com/registry/
edunpm ----- http://registry.enpmjs.org/
切换镜像 :nrm use 镜像名
例如:
C:\WINDOWS\system32>nrm use taobao
Registry has been set to: https://registry.npm.taobao.org/
6:测速:
C:\WINDOWS\system32>nrm test
npm ---- 4480ms
yarn --- 2979ms
cnpm --- 1092ms
* taobao - 326ms
nj ----- Fetch Error
npmMirror 6259ms
edunpm - Fetch Error
C:\WINDOWS\system32>
7:创建项目
这里也可以随便创建一个空文件夹,或用hbuilder工具创建一个空项目
8:初始化项目
进入项目目录
npm init -y
执行初始化命令后会多一个package.json文件
9:安装 vue
说明:
安装成功会多出node_modules
这时候就可以编写一个简单地vue项目了
--save是本地安装 -g 是全局安装
具体安装命令例如:
npm install vue --save
如果看到node_modules文件夹就说明安装成功了
4: npm其他命令
查看可安装的版本
npm view jquery versions
安装带有版本号的插件
npm install bootstrap@3.3.7 --save
npm install jquery@2.1.1 --save
模板语法
插值
普通文本插值
<div id="app">
<!--插入一个普通的文本 或json对象 包括jsonarr-->
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
html插值
<div id="app">
<div v-html="message"></div>
</div>
<script>
new Vue({
el: '#app',
data: {
message: '<h1>hello</h1>'
}
})
属性插值
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<style>
.class1{
background: #444;
color: #eee;
}
</style>
<div id="app">
<!--这里等价于<div v-bind:class="'class1'"> -->
<!--这里还可以把 【v-bind:class="a"】 缩写成 【:class="a"】-->
<div v-bind:class="a">
</div>
</div>
<script>
new Vue({
el: '#app',
data:{
a: "class1"
}
});
</script>
<div id="app">
<pre><a v-bind:href="url">百度</a></pre>
</div>
<script>
new Vue({
el: '#app',
data: {
url: 'http://www.baidu.com'
}
})
</script>
表达式插值
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<div id="app">
{{5+5}}<br>
{{ true ? 'YES' : 'NO' }}<br> <!--这里输出是yes-->
{{ false ? 'YES' : 'NO' }}<br> <!--这里输出是NO-->
</div>
<script>
new Vue({
el: '#app'
})
</script>
指令
根据指令是否显示p元素
<div id="app">
<p v-if="true">现在你看到我了我被显示了</p>
<p v-if="a">现在你看到我了</p>
</div>
<script>
new Vue({
el: '#app',
data: {
a: true
}
})
</script>
用户输入双向数据绑定
双向绑定
<div id="app">
<p>{{ message }}</p>
<input v-model="message">
</div>
<script>
new Vue({
el: '#app',
data: {
message: '我是初始值!'
}
})
</script>
指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。
过滤器
vue.js允许你自定义过滤器,被用作一些常见的文本格式化。由"管道符"指示, 格式如下:
<div id="app">
<!--fun1是调用过滤器函数,把message传入此函数-->
<!--fun2是调用过滤器函数,把fun1的返回值传入此函数-->
{{ message | fun1 | fun2}} <!--最后输出应该是“value_=” -->
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'value'
},
filters: {
//这是过滤器函数,接收管道左边的值message
fun1 (v) {
return v+"_"//过滤原字符串添加一个"_"
},
fun2 (v) {
return v+"=" //过滤原字符串添加一个"="
}
}
})
</script>
缩写
v-bind 缩写
<!-- 完整语法 -->
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>
v-on 缩写
<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
条件语句
v-if语句
<div id="app">
<p v-if="b">现在你看到我了如果b的值是false就看不到我了</p>
</div>
<script>
new Vue({
el: '#app',
data: {
b: true
}
})
</script>
v-else语句
<div id="app">
<div v-if="false">
如果是true就显示我
</div>
<div v-else>
否则选择我
</div>
</div>
<script>
new Vue({
el: '#app'
})
</script>
v-else-if
<div id="app">
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
type: 'D'
}
})
</script>
v-show
<div id="app">
<h1 v-show="ok">Hello!</h1>
</div>
<script>
new Vue({
el: '#app',
data: {
ok: true
}
})
</script>
循环语句
循环array
<div id="app">
<ol>
<li v-for="user in users">
{{ user.name}} {{ user.age}}
</li>
</ol>
</div>
<script>
new Vue({
el: '#app',
data: {
users: [
{ name: 'zhnagsan',age: 12 },
{ name: 'lisi' ,age: 13 },
{ name: 'wangwu' ,age: 14 }
]
}
})
</script>
迭代对象
<div id="app">
<ul>
<li v-for="value in user">
{{ value }}
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
user: {
name: 'zhangsan',
age: 13,
sex: '男'
}
}
})
</script>
嵌套循环一个jsonarr
<div id="app">
<table border="1">
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
</tr>
<tr v-for="user in users">
<td v-for="u in user">{{u}}</td>
</tr>
</table>
</div>
<script>
new Vue({
el: '#app',
data: {
users:[
{id:1,name: 'zhnagsan',age: 12 },
{id:2, name: 'lisi' ,age: 13 },
{id:3, name: 'wangwu' ,age: 14 }
]
}
})
</script>
也可以提供第二个的参数为键名
<div id="app">
<ul>
<li v-for="(value, key) in user">
{{ key }} : {{ value }}
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
user: {
name: '张三',
age: 13,
sex: '男'
}
}
})
</script>
第三个参数为索引:
<div id="app">
<ul>
<li v-for="(value, key, index) in user">
{{ key }} : {{ value }} : {{index}}
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
user: {
name: '张三',
age: 13,
sex: '男'
}
}
})
</script>
实战案例不显示id通过索引来控制
<div id="app">
<table border="1">
<tr>
<th>name</th>
<th>age</th>
</tr>
<tr v-for="user in users">
<td v-if="index!=0" v-for="(value,key,index) in user">{{value}}</td>
</tr>
</table>
</div>
<script>
new Vue({
el: '#app',
data: {
users:[
{id:1,name: 'zhnagsan',age: 12 },
{id:2, name: 'lisi' ,age: 13 },
{id:3, name: 'wangwu' ,age: 14 }
]
}
})
</script>
实战案例不显示key来控制
<div id="app">
<table border="1">
<tr>
<th>name</th>
<th>age</th>
</tr>
<tr v-for="user in users">
<td v-if="key!='id'" v-for="(value,key) in user">{{value}}</td>
</tr>
</table>
</div>
<script>
new Vue({
el: '#app',
data: {
users:[
{id:1,name: 'zhnagsan',age: 12 },
{id:2, name: 'lisi' ,age: 13 },
{id:3, name: 'wangwu' ,age: 14 }
]
}
})
</script>
迭代整数
<div id="app">
<ul>
<li v-for="n in 10">
{{ n }}
</li>
</ul>
</div>
<script>
new Vue({
el: '#app'
})
</script>
计算属性
字符串倒序
<div id="app">
{{ message.split('').reverse().join('') }}
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'ABC!'
}
})
</script>
computed 和methods
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ fun1 }}</p>
<p>使用方法后反转字符串: {{ fun2() }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'ABC'
},
computed: {
fun1 () {
return this.message.split('').reverse().join('')
}
},
methods: {
fun2 () {
return this.message.split('').reverse().join('')
}
}
})
</script>
computed 属性默认只有 getter ,不过在需要时你也可以提供一个 setter
<div id="app">
<p>{{ jisuan }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
name: '我是原来的老值'
},
computed: {
jisuan: {
// getter
get () {
return this.name
},
// setter
set (newValue) {
this.name = newValue
}
}
}
})
// 调用 setter, vm.name 和 vm.url 也会被对应更新
alert("调get方法获取老值为: "+vm.jisuan)
//调set方法赋新值
vm.jisuan = '新值';
alert("调get方法获取新值为: "+vm.jisuan)
</script>
监听属性
外部编写监听属性
<div id = "app">
<p style = "font-size:25px;">计数器: {{ counter }}</p>
<button @click = "counter++">点我</button>
</div>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
//这个属性将要被监听
counter: 1
}
});
//用watch监听属性counter ,我们可以通过 watch 来响应数据的变化
//watch是vue的一个属性不是自定义属性 和data、el、methods都是平级的。
//访问vue的属性是需要加上$符号的 例如:$watch、$data等
vm.$watch('counter', function(newval, olderval) {
alert('我正在监听计数器值的变化 :' + olderval + ' 变为 ' + newval + '!');
});
</script>
内部编写监听
<div id="div">
<button @click="fun1()">counter加一</button>
<br>
<button @click="b+=2">监听b</button><br>
counter:{{counter}}<br>
b: {{b}}
</div>
<script type="text/javascript">
new Vue({
el:"#div",
data:{
counter:0,
b:0
},
methods:{
fun1(){
this.counter += 1
}
},
watch:{
//监听的属性名和函数名名一致
counter(newvalue,oldervalue){
alert("counter: "+newvalue+" "+oldervalue)
},
b(newvalue,oldervalue){
alert("b: "+newvalue+" "+oldervalue)
}
}
})
</script>
内部编写监听属性
计算米和千米之间的转换
watch是监听属性的vue属性不是自定义属性
<div id = "computed_props">
千米 : <input type = "text" v-model = "kilometers">
米 : <input type = "text" v-model = "meters">
</div>
<script type = "text/javascript">
var vm = new Vue({
el: '#computed_props',
data: {
kilometers : 0,
meters:0
},
watch : {
//这个是监听kilometers属性 方法名就是要监听的属性名
kilometers() {
this.meters = this.kilometers * 1000
},
//这个是监听meters属性 方法名就是要监听的属性名
meters () {
this.kilometers = this.meters/ 1000;
}
}
});
</script>
样式绑定
class 属性绑定
我们可以为 v-bind:class 设置一个对象,从而动态的切换 class:
案例1:显示 class
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
</style>
<div id="app">
<div v-bind:class="{ 'active': isActive }"></div>
</div>
<script>
new Vue({
el: '#app',
data: {
isActive: true
}
})
</script>
点击按钮显示和禁用class
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
</style>
<div id="app">
<div :class="{'active': b}"></div>
<button @click="b=true">启用active样式</button>
<button @click="b=false">禁用active样式</button>
</div>
<script>
new Vue({
el:"#app",
data:{
b:false
}
})
</script>
案例2:切换 class
<style>
.active1 {
width: 100px;
height: 100px;
background: green;
}
.active2 {
width: 100px;
height: 100px;
background: yellow;
}
</style>
<div id="app">
<div :class="{'active1': b1,'active2':b2}"></div>
<button @click="b1=true;b2=false">启用active1样式</button>
<button @click="b2=true;b1=false">禁用active2样式</button>
</div>
<script>
new Vue({
el:"#app",
data:{
b1:true,
b2:false
}
})
</script>
绑定多个样式
<style>
.widthheight {
width: 100px;
height: 100px;
background: red;
}
.solid {
width: 100px;
height: 100px;
border: solid black;
}
</style>
<div id="app">
<!--通过属性绑定两个样式-->
<!--相当于 <div v-bind:class="['widthheight','solid']"></div> -->
<div v-bind:class="[a, b]"></div>
</div>
<script>
new Vue({
el: '#app',
data: {
a: 'widthheight',
b: 'solid'
}
})
</script>
内联样式绑定
<div id="app">
<div v-bind:style="{ color: a1, fontSize: a2 + 'px' }">我是div被内联样式控制</div>
</div>
<script>
new Vue({
el: '#app',
data: {
a1: 'red',
a2: 50
}
})
</script>
也可以直接绑定一个样式对象
<div id="app">
<div v-bind:style="styleObject">hello</div>
</div>
<script>
new Vue({
el: '#app',
data: {
styleObject: {
color: 'green',
fontSize: '30px'
}
}
})
v-bind:style 可以使用数组将多个样式对象应用到一个元素上:
<div id="app">
<div v-bind:style="[a, b]">hello</div>
</div>
<script>
new Vue({
el: '#app',
data: {
a: {
color: 'green',
fontSize: '30px'
},
b: {
//添加边框 加粗效果
'font-weight': 'bold'
}
}
})
</script>
事件处理器
单击事件弹出框
<div id="app">
<button v-on:click="alert('我被点击了')">单击事件</button>
</div>
<script>
new Vue({
el: '#app'
})
</script>
双击事件
<div id="app">
<input v-on:dblclick="alert(123)" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
change内容发生改变事件
<div id="app">
<input v-on:change="alert(213)" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
键盘按下事件
<div id="app">
<input v-on:keydown="alert(213)" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
键盘松开事件
<div id="app">
<input v-on:keyup="alert(213)" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
鼠标按下事件
<div id="app">
<input v-on:mousedown="alert(213)" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
鼠标松开事件
<div id="app">
<input v-on:mouseup="alert(213)" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
当鼠标在此元素上离开时触发事件
<div id="app">
<input v-on:mouseout="alert(213)" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
鼠标在此元素上移动时发生的事件
<div id="app">
<input v-on:mousemove="alert('移动事件')" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
鼠标进入此元素时触发事件
<div id="app">
<input v-on:mouseover="alert('鼠标进入')" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
获取焦点事件
<div id="app">
<input v-on:focus="alert('获取焦点事件')" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
失去焦点事件
<div id="app">
<input v-on:focusout="alert('失去焦点事件')" />
</div>
<script>
new Vue({
el: '#app'
})
</script>
单击事件调一个方法
<div id="app">
<button v-on:click="fun1()">点击</button>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
name: 'Vue.js'
},
methods: {
fun1() {
//
alert(event.target.tagName)
//event.srcElement event.target
}
}
})
</script>
也可以直接用javascript调用一个函数和访问一个属性
<script>
var vue = new Vue({
data:{
name:"张三"
},
methods: {
fun1 () {
alert('hello')
}
}
})
// 也可以用 JavaScript 直接调用方法
vue.fun1()
//直接访问vue的属性
alert(vue.name)
</script>
表单双向绑定
输入框
单行文本
<div id="app">
<input v-model="message1">
<p>{{ message1 }}</p>
<textarea v-model="message2"></textarea>
<p>{{ message2 }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message1: 'message1',
message2: 'message2'
}
})
</script>
输入框
多行文本
<div id="div">
<textarea v-model="userName"></textarea>
{{userName}}
</div>
<script type="text/javascript">
new Vue({
el:"#div",
data:{
userName:"初始设置"
}
});
</script>
单个复选框
<div id="app">
<p>单个复选框:</p>
<input type="checkbox" v-model="checked">
<label>{{ checked }}</label>
</div>
<script>
new Vue({
el: '#app',
data: {
checked : false
}
})
</script>
多个复选框
<div id="app">
<input type="checkbox" value="A" v-model="checkedNames">
<label>百度</label>
<br>
<input type="checkbox" value="B" v-model="checkedNames">
<label>谷歌</label>
<br>
<span>选择的值为: {{ checkedNames }}</span>
</div>
<script>
new Vue({
el: '#app',
data: {
checkedNames: []
}
})
</script>
多个复选框默认勾选A和B
<div id="app">
<input type="checkbox" value="A" v-model="values">
<input type="checkbox" value="B" v-model="values">
<input type="checkbox" value="C" v-model="values">
{{values}}
</div>
<script>
new Vue({
el: '#app',
data: {
//当values是数组类型的时候 绑定checkbox是追加数据而不是替换数据
values : ["A","B"]
}
})
</script>
change事件实现全选和反选效果
<div id="app">
<input type="checkbox" v-model="b" v-on:change="fun1()"/> <br>
<input type="checkbox" value="A" v-model="values">
<input type="checkbox" value="B" v-model="values">
<input type="checkbox" value="C" v-model="values">
{{values}}
</div>
<script>
new Vue({
el: '#app',
data: {
//当values是数组类型的时候 绑定checkbox是追加数据而不是替换数据
values : [],
b:false
},
methods:{
fun1(){
if(this.b){
this.values=['A','B','C']
}else{
this.values=[]
}
}
}
})
</script>
单选按钮
<div id="app">
<input type="radio" value="A" v-model="picked">
<label>百度</label>
<br>
<input type="radio" value="B" v-model="picked">
<label>谷歌</label>
<br>
<span>选中值为: {{ picked }}</span>
</div>
<script>
new Vue({
el: '#app',
data: {
picked : 'A'
}
})
</script>
下拉框
<div id="app">
<select v-model="value">
<option value="">-请选择一个选项--</option>
<option value="A">你选中了A</option>
<option value="B">你选中了B</option>
<option value="C">你选中了C</option>
</select>
{{value}}
</div>
<script>
new Vue({
el: '#app',
data: {
value : '' //value值是哪一个选项将被默认选择这一项
}
})
</script>
自定义组件
语法:Vue.component(tagName, options)
<div id="app">
<a1></a1>
</div>
<script>
// 注册
Vue.component('a1', {
template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
局部组件
<div id="app">
<a1></a1>
</div>
<script>
var Child1 = {
template: '<h1>自定义组件!</h1>'
}
// 创建根实例
new Vue({
el: '#app',
components: {
'a1': Child1
}
})
</script>
props
作用是父组件向子组件传递数据
<div id="app">
<child pname1="我是属性值1" pname2="我是属性值2"></child>
</div>
<script>
// 注册
Vue.component('child', {
props: ['pname1','pname2'],
template: '<span>插入属性值: {{ pname1 }} {{pname2}}</span>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
动态prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件
<div id="app">
<div>
<input v-model="parentMsg">
<br>
<child v-bind:pname="parentMsg"></child>
</div>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['pname'],
// 同样也可以在 vm 实例中像 “this.message” 这样使用
template: '<span>{{ pname }}</span>'
})
// 创建根实例
new Vue({
el: '#app',
data: {
parentMsg: '父组件内容'
}
})
</script>
父组件给子组件传一个动态绑定的user
<div id="app">
id:<input v-model="user.id"/>
userName:<input v-model="user.userName"/>
<a1 v-bind:pn1="user"></a1>
</div>
<script>
Vue.component("a1",{
template:
`
<span>{{pn1.id}} -- {{pn1.userName}}</span>
`,
props:["pn1"]
})
new Vue({
el:"#app",
data:{
user:{id:1,userName:"张三"}
}
})
</script>
循环组件,每循环一次父组件给子组件传一个user
<div id="div">
<input v-model="users[0].id" />
<tag1 v-bind:user1="user" v-for="user in users" ></tag1>
</div>
<script>
//自定义一个组件 传入user对象
Vue.component("tag1",{
template:
`
<span>
<hr>
<ul>
<li>{{user1}}</li>
</ul
</span>
<hr>
`,
props:["user1"]
})
//创建vue对象
new Vue({
el:"#div",
data:{
users:
[
{ userName: '张三',password:"123" },
{ userName: '李四',password:"234" },
{ userName: '王五',password:"345" }
]
}
})
</script>
组件内部也可以定义函数
<div id="div">
<tag1></tag1>
</div>
<script>
//自定义一个组件 传入user对象
Vue.component("tag1",{
template:
`
<span>
<button v-on:click="mothod1()">点我一下</button>
</span>
`,
methods:{
mothod1(){
alert("我被点击了")
}
}
})
//创建vue对象
new Vue({
el:"#div",
methods:{
method2(){
alert(1231)
}
}
})
</script>
自定义子组件属性
自定义组件里面的data 必须是一个函数,通过调用函数获属性
<div id="div">
<tag1></tag1>
</div>
<script>
//自定义一个组件 传入user对象
Vue.component("tag1",{
template:
`
<span>
<button v-on:click="mothod1()">点我一下</button>
</span>
`,
methods:{
mothod1(){
alert(this.name+" "+this.age)
}
},
data:function(){
return {
name:"q3",
age:12
}
}
})
//创建vue对象
new Vue({
el:"#div",
methods:{
method2(){
alert(1231)
}
}
})
</script>
组件 - 自定义事件
内部函数触发外部函数无参数
<div id="div">
<tag1 v-on:event1="func2()"></tag1>
</div>
<script type="text/javascript">
Vue.component("tag1",{
template:
`
<button v-on:click="func1()">点击我</button>
`,
methods:{
func1(){
//添加一个触发外部的自定义事件
this.$emit("event1")
}
}
})
new Vue({
el:"#div",
methods:{
func2(){
alert(222)
}
}
})
</script>
内部函数触发外部函数无参数
<div id="app">
<div id="counter-event-example">
<p>{{ total }}</p>
<!-- 第三步当这个event1事件被触发时,调fun2()函数,event1 由内向外触发 -->
<button1 v-on:event1="fun2()"></button1>
<button1 v-on:event1="fun2()"></button1>
</div>
</div>
<script>
Vue.component('button1', {
//第一步:当按钮被点击时触发fub1()函数
template: '<button v-on:click="fun1()">请点击按钮</button>',
methods: {
fun1 () {
// 第二步:触发外部event1事件 emit 发出
this.$emit('event1')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
fun2 () {
this.total += 1
}
}
})
</script>
内部函数向外部函数传简单数据
<div id="div">
<button1 v-on:event1="fun2($event)"></button1>
</div>
<script>
Vue.component('button1', {
template: '<button v-on:click="fun1()">请点击按钮</button>',
methods: {
fun1 () {
this.$emit('event1','我是子组件的数据被到父组件了。')
}
},
})
new Vue({
el: '#div',
methods: {
fun2 (a) {
//输出子组件传过来的数据
alert(a)
}
}
})
</script>
内部函数向外部函数传json数据
<div id="div">
<!--$event是接收参数-->
<button1 v-on:event1="fun2($event)"></button1>
</div>
<script>
Vue.component('button1', {
template: '<button v-on:click="fun1()">请点击按钮</button>',
data: function(){
return{
user:{name:"zhagsan",age:13}
}
},
methods: {
fun1 () {
//$emit向外触发一个自定义的事件 event1是事件名
this.$emit('event1',this.user)
}
},
})
new Vue({
el: '#div',
methods: {
fun2 (user) {
//输出子组件传过来的数据
alert(user.name+" "+user.age)
}
}
})
</script>
内部函数向外部函数传表单数据
<div id="div">
<button1 v-on:event1="fun2($event)"></button1>
</div>
<script>
Vue.component('button1', {
template: `
<p>
userName:<input v-model="user.name"> <br>
password: <input v-model="user.age"><br>
<button @click="fun1()">点击我</button>
</p>
`
,
data: function(){
return{
user:{name:"zhagsan",age:13}
}
},
methods: {
fun1 () {
this.$emit('event1',this.user)
}
},
})
new Vue({
el: '#div',
methods: {
fun2 (user) {
//输出子组件传过来的数据
alert(user.name+" "+user.age)
}
}
})
</script>
组件内部元素不显示的问题
例如:
这个是正确的可以正常显示
template: `
<p>
userName:<input v-model="user.name"> <br>
password: <input v-model="user.age"><br>
<button @click="fun1()">点击我</button>
</p>
这个是正确的可以正常显示
template: `
<span>
<div>A</div>
<div>A</div>
</span>
`
这个是不正常的,是不能正常显示的
<p>
<div>A</div>
<div>A</div>
<input>
<input>
</p>
全局属性
<div id="div">
<button2></button2>
<button2></button2>
<button2></button2>
</div>
<script>
//count是全局属性
var abc = { count: 0}
Vue.component('button2', {
data: function () {
// data 选项是一个对象(外部对象),会影响到其他实例
return abc
},
template: '<button v-on:click="count++">点击了 {{ this.count }} 次。</button>'
})
new Vue({
el: '#div' ,
})
</script>
局部属性
<div id="div">
<button2></button2>
<button2></button2>
<button2></button2>
</div>
<script>
Vue.component('button2', {
data: function () {
// count是局部属性
return { count: 0}
},
template: '<button v-on:click="count++">点击了 {{ this.count }} 次。</button>'
})
new Vue({
el: '#div' ,
})
</script>
组件内部input元素和外面属性进行双向绑定
<div id="app">
<runoob-input v-model="num"></runoob-input>
<p>输入的数字为:{{num}}</p>
</div>
<script>
//<input v-model="parentData">
Vue.component('runoob-input', {
template: `
<p> <!-- 包含了名为 input 的事件 -->
<input :value="value" @input="$emit('input', $event.target.value)">
</p>
`,
props:["value"]
})
new Vue({
el: '#app',
data: {
num: 100,
}
})
</script>
Vue.js Ajax(axios)
Axios是什么:
Axios是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中
promise是什么:
1、主要用于异步计算 2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果 3、可以在对象之间传递和操作promise,帮助我们处理队列
安装axios:
使用 cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
或者
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
再或者直接下载axios.min.js文件
案例1:
axios.get("url",{ withCredentials: true}) //保持登录状态
axios.defaults.withCredentials = true;//保持登录状态
axios.get("url")
案例2:
axios.get("child.html").then(function(response){
alert(response.data)
})
案例3:
axios.get("child.html").then(response => alert(response.data))
案例4:回调函数
语法是:axios.get(url).then(calbackfunction); //和jquery的ajax一样返回的是json数据
<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<div id="div">
<table border="1">
<td>id</td>
<td>userName</td>
<td>password</td>
<tr v-for="user in users">
<td>{{user.id}}</td>
<td>{{user.userName}}</td>
<td>{{user.password}}</td>
</tr>
</table>
</div>
<script type="text/javascript">
new Vue({
el:"#div",
data:{
users:[]
},
created() {
var this_ = this;
axios.get("http://localhost:8080/getUsers").then(function(data){
this_.users = data.data;
})
}
})
</script>
案例3:简写回调函数
<div id="div">
<table border="1">
<tr>
<th>userName</th>
<th>password</th>
</tr>
<tr v-for="user in users">
<td v-if="key != 'id'" v-for="(value,key) in user">{{value}}</td>
</tr>
</table>
</div>
<script type="text/javascript">
new Vue({
el:"#div",
data:{
users:[]
},
created() {
axios.get("http://localhost:8080/getUsers").
then(response => this.users = response.data)
}
})
</script>
get传参数
第一种
axios.post("http://localhost:8080/getUsers?id=1&name=张三")
第二种
axios.get("http://localhost:8080/getUsers",{params:{id:2, name:"lisi"}})
post传参数
axios.post("http://localhost:8080/getUsers?id=1&name=张三")
var data = new FormData()
data.append("id",1)
data.append("name","zhangsan")
axios.post("http://localhost:8080/getUsers",data)
发送多个ajax请求
语法:
ajax1(){
axios.get("http://localhost:8080/ajax1")
.then(response => alert(response))
}
ajax2(){
axios.get("http://localhost:8080/ajax2")
.then(response => alert(response))
}
axios.all([ajax1(), ajax2()]).then(alert("success"))
案例:
<div id="div">
{{a}} ---- {{b}}
</div>
<script>
new Vue({
el:"#div",
data:{
a:"a",
b:"b"
},
created() {
axios.all([this.ajax1(), this.ajax2()]).then(alert("success"))
},
methods:{
ajax1(){
axios.get("http://localhost:8080/ajax1")
.then(response => this.a = response.data)
},
ajax2(){
axios.get("http://localhost:8080/ajax2")
.then(response => this.b = response.data)
}
}
})
</script>
文件上传
前端
<script src="js/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
<input id="file" type="file"
accept="image/png,image/gif,image/jpeg"
@change="upload"/>
</div>
<script>
new Vue({
el:"#app",
methods:{
upload () {
var file = document.getElementById("file").files[0]
var param = new FormData() // 创建form对象
param.append('file', file) // 通过append向form对象添加数据
param.append('chunk', 'hello') // 添加form表单中其他数据
var config = {
headers: {'Content-Type': 'multipart/form-data'}
}
axios.post("http://localhost:8080/upload",param,config).then(response =>{
alert(response.data)
})
}
}
})
</script>
后端
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file, String chunk) {
if (file.isEmpty()) {
return "上传失败,请选择文件";
}
String fileName = file.getOriginalFilename();
String filePath = this.getClass().getResource("/").getPath();
new File(filePath + "static").mkdirs();
File dest = new File(filePath + "static/"+fileName);
System.out.println(dest.getPath());
try {
file.transferTo(dest);
System.out.println("上传成功");
} catch (IOException e) {
e.printStackTrace();
}
return "success";
}
钩子函数以及生命周期
<div id="app">
<p>{{ message }}</p>
<button onclick="update()">update</button>
<button onclick="delete1()">update</button>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message : "xuxiao is boy"
},
beforeCreate: function () {
console.group('beforeCreate 创建前状态===============》');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message) //undefined
},
created: function () {
console.group('created 创建完毕状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeMount: function () {
console.group('beforeMount 挂载前状态===============》');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
mounted: function () {
console.group('mounted 挂载结束状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeUpdate: function () {
console.group('beforeUpdate 更新前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
updated: function () {
console.group('updated 更新完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
beforeDestroy: function () {
console.group('beforeDestroy 销毁前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
destroyed: function () {
console.group('destroyed 销毁完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
})
function update(){
app.message="AAAA"
}
function delete1(){
//app.message="AAAA"
app.$destroy();
}
</script>
三级菜单演示案例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="node_modules/axios/dist/axios.js"></script>
<script src="node_modules/vue/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script src="node_modules/jquery/dist/jquery.js"></script>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css">
<script src="node_modules/bootstrap/dist/js/bootstrap.js"></script>
<script src="./js/header.js" type="text/javascript" charset="utf-8"></script>
<script src="./js/foot.js" type="text/javascript" charset="utf-8"></script>
<script src="./js/navigationElement.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="div">
<form class="form-inline" role="form">
<select style="width: 300px;" class="form-control" v-model="value1" @change="loadSelect2(value1)">
<option value="--请选择--">--请选择--</option>
<option v-bind:value="category.id" v-for="category in categorys1">{{category.id}} -- {{category.categoryName}}</option>
</select>
<select style="width: 300px;" class="form-control" v-model="value2" @change="loadSelect3(value1)">
<option value="--请选择--">--请选择--</option>
<option v-bind:value="category.id" v-for="category in categorys2">{{category.id}} -- {{category.categoryName}}</option>
</select>
<select style="width: 300px;" class="form-control" v-model="value3">
<option value="--请选择--">--请选择--</option>
<option v-bind:value="category.id" v-for="category in categorys3">{{category.id}} -- {{category.categoryName}}</option>
</select>
</form>
</div>
<script>
var vue = new Vue({
el:"#div",
data:{
value1:"",
value2:"",
value3:"",
categorys1:[],
categorys2:[],
categorys3:[]
},
created() {
this.loadSelect1(0)
},
methods:{
loadSelect1(parentId){
this.value1="--请选择--"
axios.get("http://localhost:8081/getCategorys?parentId="+parentId).then(response => {
this.categorys1 = response.data
})
},
loadSelect2(parentId){
this.value2="--请选择--"
axios.get("http://localhost:8081/getCategorys?parentId="+parentId).then(response => {
this.categorys3 = []
this.categorys2 = response.data
})
},
loadSelect3(parentId){
this.value3="--请选择--"
axios.get("http://localhost:8081/getCategorys?parentId="+parentId).then(response => {
this.categorys3 = response.data
})
}
}
})
</script>
</body>
</html>
@Resource
CateGoryMapper cateGoryMapper;
public List<Category> getChildsId(Long parentId){
List<Category> categories = new ArrayList<Category>();
if(parentId==0){
categories = cateGoryMapper.getParents();
}else{
Category conditionCategory = new Category();
conditionCategory.setParentId(parentId);
categories = cateGoryMapper.getEntitysByEntity(conditionCategory);
}
return categories;
}
有关其他技术学习请进入 juejin.cn/user/175884…