https://cn.vuejs.org/
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。
正谷歌浏览器应用商店搜索Vue Devtools,安装即可
科学上网,然后在谷歌的应用商店安装iguge
参考地址:https://cli.vuejs.org/zh/
Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+)。你可以使用 nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。
安装环境:npm install -g @vue/cli
这里提供几种方案:
npm uninstall vue-cli -g
npm install -g @vue/cli
2.降级为vue2.x方法
npm uninstall @vue/cli -g
npm install -g vue-cli
3.vue2.x脚手架的安装和初始化项目
# 创建项目
vue init webpack 项目名字
# 注意 ,以上步骤会让你创建一个vue文件夹存放vue项目,一般是webpack项目,与html中引入vue.js有一点点区别,注意router 那块选择yes,其他的选择no
#初始化项目
npm install
# 运行项目
npm run dev
4.vue3.x脚手架的安装和初始化项目
# 创建项目
vue create 项目名字
# 项目初始化
npm install
# 启动项目
npm run dev
或者:在项目的根目录下运行:npm run serve
模板语法
参考HelloWorld.vue文件
注意事项:模板中可以放语法,单个表达式语法
CSS作用域
scoped:作用域 在Vue的文件中,也有css的作用域,增加scoped属性,样式只能在当前组件中生效
条件渲染
v-if
v-else
v-show
v-if和v-show的区别:
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
列表渲染
v-for
v-for 与 v-if 一同使用:注意我们不推荐在同一元素上使用 v-if 和 v-for
事件处理
v-on:click=“函数”
表单输入绑定
数组更新检测
数组方法的特异性:
1. 改变元素组(会引起视图更新)
push() pop() shift() unshift() splice() sort() reverse()
2. 不改变元素数组,而是生成新的数组(不会引起视图更新)
filter()、concat() 和 slice()
对象的更新检测
向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = ‘hi’)
this.$set(this.obj,“age”,20)
API参考地址:https://cn.vuejs.org/v2/api/#vm-set
计算属性与侦听器
Class 与 Style 绑定
组件
注意,此vue学习采用vue3的创建方式进行,且一开始没有创建路由,还请注意:
<template>
<div class="hello">
<p>{{ msg }}p>
<p>{{ 1+1 }}p>
<p>{{ num + 10 }}p>
<p>{{ 10 > 20 ? '真的' : '假的' }}p>
<p>{{ msg.split('').reverse().join('') }}p>
<p v-html="vHTML">p>
<p :class="bindClass">我是文本p>
<a v-bind:href="Href">iwen的站点a>
<p v-bind:attr="attr">自定义属性p>
<p :class="bindClass" class="size">动态属性与固定属性不冲突p>
<hr />
<h3 v-if="flag">我是孙悟空h3>
<h3 v-else>我是六耳猕猴h3>
<template v-if="flag">
<h3>仓央嘉措h3>
<p>站在布达拉宫p>
<p>我是雪域最大的王p>
template>
<template v-else>
<p>流浪在拉萨街头p>
<p>我是世间最美的情郎p>
template>
<p v-show="flag">我是show的展示p>
<hr />
<ul>
<li v-for="(item,index) in banner.data" v-bind:key="index">
<a v-bind:href="item.url">
<img v-bind:src="item.image" alt />
<p>{{ item.title }}p>
a>
li>
ul>
<ul>
<li v-for="(value,name,index) in userInfo" v-bind:key="index">
<span>{{ name }}span>:
<span>{{ value }}span> -
<span>{{ index }}span>
li>
ul>
<p v-for="(item,index) in names" v-bind:key="index">{{ item }}p>
<ul>
<li v-for="(diff,index) in diffs" v-bind:key="index">
<span v-if="diff.flag">{{ diff.name }}span>
li>
ul>
<button v-on:click="clickHandle">按钮1button>
<button v-on:click="counter += 1">按钮2button>
<p>{{ counter }}p>
<button v-on:click="paramsHandle('hello',$event)">按钮3button>
<ul>
<li
v-on:click="getItemHandle(item)"
v-for="(item,index) in names"
:key="index"
>{{ item }}li>
ul>
<form v-on:submit.stop.prevent="formHandle">
<button>表单按钮button>
form>
<input type="text" @keyup.enter="inputHandle" />
<hr />
<textarea type="text" v-model.lazy="username">textarea>
<p>{{ username }}p>
<div>
<input type="checkbox" id="jack" value="Jack11" v-model="checkedNames" />
<label for="jack">Jacklabel>
<input type="checkbox" id="john" value="John22" v-model="checkedNames" />
<label for="john">Johnlabel>
<input type="checkbox" id="mike" value="Mike33" v-model="checkedNames" />
<label for="mike">Mikelabel>
<span>{{ checkedNames }}span>
div>
<ul>
<li v-for="(item,index) in container" :key="index">{{ item }}li>
ul>
<button @click="addHandle">添加数据button>
<ul>
<li v-for="(value,name,index) in obj" :key="index">{{ value }}li>
<button @click="addObjHandle">添加数据button>
ul>
<p>{{ setMSG }}p>
<p>{{ setMSG }}p>
<p>{{ getMSG() }}p>
<input type="text" v-model="password">
<p>{{ password }}p>
<p :class="{ 'active':isActive,'text-danger':hasError }">class与style样式绑定p>
<ul>
<li :class="{ 'active':index === 2 }" v-for="(item,index) in container" :key="index">{{ item }}li>
ul>
<p :class="[helloActive,helloText]">数组语法p>
<p :class="[isActive ? 'active' : 'text-danger',helloActive]">数组语法2p>
<p :class="[isActive ? 'active' : 'text-danger',{ 'text-danger1':hasError }]">必须数组嵌套对象p>
<p :style="{ fontSize:fontNum + 'px',display:'flex' }">style样式p>
div>
template>
<script>
export default {
// 函数
data() {
return {
fontNum:30,
helloActive:'active',
helloText:"text-danger",
isActive:false,
hasError:true,
password:"",
container:[1,2,3,4,5],
obj:{
name:'iwen'
},
username: "",
checkedNames:[],
msg: "Hello Vue",
num: 10,
vHTML: "我是属性绑定",
bindClass: "text-2", // 动态赋值,js操作,后续可以通过事件改变
Href: "http://iwenwiki.com",
attr: "1001",
flag: false,
names: ["iwen", "ime", "frank"],
banner: {
status: 200,
data: [
{
image: "http://iwenwiki.com:3002/images/savefood1.jpg",
title: "养生从我开始,从不懈怠",
url: "http://iwenwiki.com"
},
{
image: "http://iwenwiki.com:3002/images/savefood2.jpg",
title: "以梦为马,不负韶华",
url: "http://iwenwiki.com"
},
{
image: "http://iwenwiki.com:3002/images/savefood3.jpg",
title: "都是第一次为人,凭什么我要让着你",
url: "http://iwenwiki.com"
},
{
image: "http://iwenwiki.com:3002/images/savefood4.jpg",
title: "这只猫太可恶了,我的耳机又坏了",
url: "http://iwenwiki.com"
},
{
image: "http://iwenwiki.com:3002/images/savefood5.jpg",
title: "死猫,你再咬,看我打不打你就完了",
url: "http://iwenwiki.com"
}
]
},
userInfo: {
name: "iwen",
age: 20
},
diffs: [
{
name: "蔬菜",
flag: true
},
{
name: "水果",
flag: true
},
{
name: "肉类",
flag: false
}
],
counter: 1
};
},
methods: {
clickHandle(e) {
// 修改data的数据
this.flag = !this.flag;
},
paramsHandle(data, event) {
console.log(data);
console.log(event);
},
getItemHandle(data) {
console.log(data);
},
formHandle(e) {
// e.preventDefault();
console.log(111);
},
inputHandle(e) {
// if(e.keyCode === 13){
// console.log("enter");
// }
console.log("enter");
},
addHandle(){
// this.container.push(6);
this.container = this.container.concat([6,7,8,9])
},
addObjHandle(){
// 对象的更新检测,在ES6中,我们不推荐大家直接修改对象
// this.obj.age = 20;
this.$set(this.obj,"age",20)
},
getMSG(){
return this.msg.split("").reverse().join("")
}
},
computed:{
// 计算属性的优点,如果数据源没有发生变化,则不会重新计算
setMSG(){
return this.msg.split("").reverse().join("")
}
},
watch:{
/**
* new:当前最新的数据
* old:上一次操作的数据
* 所有data中声明的属性都可以监听
* 后续学习props的属性值,也可以通过watch监听数据变化
*/
password(newPassword,oldPassword){
/**
* React中我们讲过搜索:搜索历史!
*/
console.log("newPassword:"+newPassword);
console.log("oldPassword:"+oldPassword);
if(newPassword === "123"){
console.log("临界值");
}
}
}
};
script>
<style scoped>
.text-1 {
color: red;
}
.text-2 {
color: green;
}
.size {
font-size: 30px;
}
.active{
color: red;
font-size: 30px;
}
style>
main.js文件
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<MyComponent />
<MyComponent />
<MyComponent />
div>
template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import MyComponent from "./components/MyComponent"
export default {
name: 'App',
components: {
HelloWorld,
MyComponent // 注入
}
}
script>
<style lang="less">
#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>
MyComponent.vue
<template>
<div>
创建组件:{{ num }}
<button @click=" num += 1 ">按钮button>
div>
template>
<script>
export default {
name:"MyComponent",
data(){
return{
num:0
}
},
methods:{
},
computed:{
},
watch:{
}
}
script>
<style scoped lang="less">
style>
registerServiceWorker.js
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
)
},
registered () {
console.log('Service worker has been registered.')
},
cached () {
console.log('Content has been cached for offline use.')
},
updatefound () {
console.log('New content is downloading.')
},
updated () {
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
})
}