导航
index.html
文件中写上 <div id="app"></div>
main.js
中引入 Vue//2 引入 Vue
import Vue from 'vue';
import App from './app.vue';
new Vue({
// el: '#app', // 目的地
// render: 'DOM结构' // 渲染的内容
el: '#app', // 指定父容器,表示把上面App文件中的代码插入到 index.html 中 #app 元素中去
render: function(createElement) {
return createElement(App)
// App中包含的是<template>,<script>这些东西,不识别。
// 所以我们用 createElement 将其生成为DOM结构
// #app需要render函数中生成的 dom 结构
// 所以我们还需要再 return 出去
}
})
my_project
src 存放人看得懂的源代码,具有一定功能划分(MVC)
dist 存放真实上线的代码(减少请求,混淆代码)机器能看懂
webpack.config.js 打包生成 dist 下的代码
package.json文件 包信息描述 & 运行命令 e.g. npm run dev,npm run build
// 命令行:
// npm run build 立刻读取 webpack.config.js 文件,生成到dist目录
// npm run dev (webpack-dev-server) 运行src下的代码,虚拟出build.js测试
是元素的 innerText
,只能在双标签中使用
<span v-text="{data}"></span>
是元素的 innerHTML
,不能包含表达式 {{}}
<div v-html="html">
</div>
元素是否移除或者插入
<div v-if="isShow">123123</div>
元素是否显示或者隐藏(display: none
)
双向数据绑定
本质:v-model
本质上是语法糖,即利用 v-model
绑定数据,其实就是既绑定了数据,又添加了一个 input
事件监听
v-model = @input + :value
v-model = @change + :value
v-model = @change + :checked
{{name}}<input type="text" v-model="name">
<input type="text" :value="name" @input="name = $event.target.value">
/**
* 数据双向绑定 -> v-model="数据来源" (data) 语法糖 MVVM
*
* 适用元素:input、textArea、select、checkbox、radio
*
* 使用了v-model -> Vue会忽略掉:value|checked|selected
*/
const App = {
template: `
<p>
<h2>Input</h2>
<p>{{ inputText }}</p>
<input type="text" v-model="inputText" />
@input+value:
<input type="text" :value="inputText" @input="setInputText" />
</p>
<p>
<h2>Select</h2>
如果未能匹配到对应的value,select显示的就是个空项
但这里在iOS上有个问题,空项被触发时,iOS中无法触发change事件的,用户就没有办法选择第一项
所以一般在select添加第一项为 “请选择” ,并不让选择
<p>{{ selectedValue }}</p>
<select v-model="selectedValue">
<option value="" disabled>请选择</option>
<option value="Russia">俄罗斯</option>
<option value="China">中国</option>
<option value="America">美国</option>
</select>
@change+value:
<select :value="selectedValue" @change="selectValue">
<option value="" disabled>请选择</option>
<option value="Russia">俄罗斯</option>
<option value="China">中国</option>
<option value="America">美国</option>
</select>
</p>
<p>
<h2>checkbox单选</h2>
<p>{{ cbChecked }}</p>
<input type="checkbox" v-model="cbChecked" />
@change+value:
<input type="checkbox" :value="cbChecked" @change="setCbCheckbox"/>
</p>
<p>
<h2>checkbox多选</h2>
<p>{{ selectedCountries }}</p>
俄罗斯:<input type="checkbox" value="Russia" v-model="selectedCountries" />
中国:<input type="checkbox" value="China" v-model="selectedCountries" />
美国:<input type="checkbox" value="America" v-model="selectedCountries" />
</p>
<p>
<h2>radio单选</h2>
<p>{{ gender }}</p>
男:<input type="radio" value="male" v-model="gender" />
女:<input type="radio" value="female" v-model="gender" />
</p>
<p>
<h2>动态渲染select</h2>
<p>{{ selectedValue }}</p>
<select v-model="selectedValue">
<option value="" disabled>请选择</option>
<option v-for="country of countries"
:key="country.id"
:value="country.value">
{{ country.info.name }}
</option>
</select>
</p>
<p>
<h2>checkbox值绑定</h2>
<p>{{ married }}</p>
婚否:
<input
type="checkbox"
v-model="married"
true-value="married"
false-value="unmarried"
/>
</p>
<p>
<h2>radio值绑定</h2>
<p>{{ isAgree }}</p>
<input
type="radio"
v-model="isAgree"
:value="isAgreeValue"
/>
</p>
<p>
<h2>绑定对象</h2>
<p>{{ selectedValue2 }}</p>
<select v-model="selectedValue2" @change="">
<option value="" disabled>请选择</option>
<option value="{ name: '俄罗斯', continent: 'Euro' }">俄罗斯</option>
<option value="{ name: '中国', continent: 'Asia' }">中国</option>
<option value="{ name: '美国', continent: 'North America' }">美国</option>
</select>
</p>
<p>
<h2>lazy</h2>
<p>{{ inputText }}</p>
<p>@input+value:每次输入完成后,数据发生变化</p>
<input type="text" v-model="inputText" />
<p>@change+value:失去焦点时,数据改变</p>
<input type="text" v-model.lazy="inputText" />
</p>
<p>
<h2>number</h2>
<p>typeof类型:{{ typeof myNumber1 }}</p>
<p>typeof类型:{{ typeof myNumber2 }}</p>
普通 type="number" 返回的是 number 类型,空值为 string:
<br>
<input type="number" v-model="myNumber1" />
<br>
加了 v-model.number 返回的也是 number 类型,但值如果无法被 parseFloat 解析,就返回原始的值;空值仍然是0:
<input type="number" v-model.number="myNumber2" />
</p>
<p>
<h2>trim</h2>
<p>{{ myText1.length }}</p>
<p>{{ myText2.length }}</p>
<input type="text" v-model="myText1" />
<input type="text" v-model.trim="myText2" />
</p>
<p>
<h2>v-model不会在输入法没确认之前(输入汉字、韩文...时)变化</h2>
<p>{{ myText3 }}</p>
<input type="text" v-model="myText3" />
<input type="text" @input="setMyText3" :value="myText3" />
</p>
`,
data() {
return {
inputText: 'inputText',
selectedValue: '',
cbChecked: false,
selectedCountries: [],
gender: 'male',
countries: [
{id: 1, info: { name: '俄罗斯', continent: 'Euro' }, value: 'Russia'},
{id: 2, info: { name: '中国', continent: 'Asia' }, value: 'China'},
{id: 3, info: { name: '美国', continent: 'North America' }, value: 'America'},
],
married: 'unmarried',
isAgree: false,
isAgreeValue: '同意',
selectedValue2: '',
myNumber1: 1,
myNumber2: 2,
myText1: '',
myText2: '',
myText3: ''
}
},
methods: {
setInputText(e) {
this.inputText = e.target.value;
},
selectValue(e) {
this.selectedValue = e.target.value;
},
setCbCheckbox(e) {
this.cbChecked = e.target.checked;
},
setMyText3(e) {
this.myText3 = e.target.value;
}
}
};
Vue.createApp(App).mount('#app');
VInput 组件
<template>
<input type="checkbox" :checked="checked" @change="updateSomething" />
</template>
<script>
export default {
// 自定义事件名或属性名要在 model 中定义
model: {
prop: "checked", // 属性
event: "change", // 事件
},
props: {
checked: {
type: Boolean,
default: false,
},
},
methods: {
// 通过发布自定义事件更新
updateSomething(e) {
this.$emit("change", e.target.checked);
},
},
};
</script>
父组件使用
<template>
<div>
<v-input :checked="checked" @change="change"></v-input>
<!--上边或者这种写法: <v-input v-model="checked"></v-input> -->
</div>
</template>
<script>
import VInput from "./components/VInput";
export default {
name: "tran-con-list",
data() {
return {
checked: false,
};
},
components: {
VInput,
},
methods: {
handler(num, e) {
console.log(num, e);
},
change(value) {
console.log(value);
},
},
watch: {
checked(val) {
console.log(val);
},
},
};
</script>
:prop.sync="prop"
this.$emit("update:prop", value)
子组件
父组件
<!--调用方式-->
<template>
<custom-overlay :visible.sync="visible" />
</template>
<script>
export default {
data() {
return {
visible: false
};
}
};
</script>
单项数据绑定(内存 js 影响页面)
// 格式
// v-bind:属性名='表达式'
<div v-bind:class="isRed ? 'red' : 'green'">123123</div>
// 简写形式:
<div :class="isRed ? 'red' : 'green'">123123</div>
// 如果不加 v-bind,class里面的表达式就是个字符串
// 一个样式
stus: [{name: 'Lance',score: 'A'},{name: 'Jerry',score: 'B'}]
// v-for循环体写在li上
<ul>
<li
v-for="(stu, index) in stus"
:key="index" :class="{'A': 'red', 'B': 'green'}[stu.score]">
{{stu.name}}
</li>
// or
<li :class="stu.score == 'A' ? 'red' : 'green'">
{{stu.name}}
</li>
</ul>
// 多个样式
// {'类名': 表达式, '类名': 表达式}
<div v-bind:class="{'red': isRed, 'big': isBig}">123123</div>
格式:v-on:事件名="表达式||函数名" 函数名如果没有参数,可以省略(),只给一个函数名称
<button v-on:click="onChange()">点我改变</button>
// 简写形式:
<button @click="onChange()">点我改变</button>
methods {
onChange() {...}
}
.stop 阻止冒泡 @click.stop="btnHandler"
.prevent 阻止默认事件 @click.prevent
.capture 添加事件监听器时使用事件捕获模式
@click.capture
再来点击子元素时,就会先打印父元素被点击,再打印子元素被点击.self 只有当事件在该元素本身(比如不是子元素)时触发回调
.once 事件只触发一次
.enter .tab .delete(捕获“删除”和“退格”键) .esc .space
// 按下f2键(键码113)后触发的事件
<input ... @keyup.113 = 'addHero'>
// 为了更好地语义,配置键值
// f2的按键码是113,现在我们给它取名为f2,方便使用时更符合语义
Vue.config.keyCodes.f2 = 113
<input ... @keyup.f2 = 'addHero'>
推荐将 v-for 写在子元素上(li)
需要添加 key ,这是为了告诉vue,js中的元素与页面之间的关联。当视图删除元素的时候,是单个元素的删除而不是整个替换,所以需要关联其关系。必须添加key(提高性能)
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
还可以遍历一个方法,该方法返回一个数组就OK,这样我们就可以给方法传值
<input type="text" v-model="keywords">
<li v-for="(item, index) in search(keywords)" :key="index">
search(keywords) {
return ...
}
解决 插值表达式闪烁的问题
<p v-clock>{{ msg }}</p>
// 网络不好的情况下,如果不加v-cloak,会导致加载时显示字符串{{ msg }},加载完后才显示msg变量的值
// 解决办法:
// 给元素加上 v-clock,并添加属性选择器 [v-cloak] { display: none; }
介绍:
Vue.directive()
directives: {'fontweight': {bind:function() {}, ...}}
参数:
// 实现加载完页面后,某表单元素自动获取焦点
// 目标,为元素添加指令:“v-focus” 即可获取焦点
Vue.directive('focus', {
bind: function (el) { // 每当指令绑定到元素上时,会立即执行这个函数,只执行一次
// 注意:在每个函数中,第一个参数永远是 el ,表示被绑定了指令的那个元素。
// 这个 el 参数,是一个原生的JS对象
// 在元素刚绑定了指令的时候,还没有插入到DOM中去,这时候,调用 focus 方法没有作用
// 因为,一个元素,只有插入DOM之后,才能获取焦点
// el.focus() 无效
},
inserted: function (el) { // 元素插入到DOM中的时候,会执行 inserted 函数【触发1次】
el.focus()
// 和JS行为有关的操作,最好在 inserted 中去执行,放置 JS行为不生效
},
updated: function (el) { // 当VNode更新的时候,会执行 updated, 可能会触发多次
}
})
// 自定义一个 设置字体颜色的 私有指令 和 简写指令
directives: {
'color': {
// 样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式
// 将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素
bind: function (el, binding) {
// el.style.color = 'red'
// console.log(binding.name)
// 和样式相关的操作,一般都可以在 bind 执行
// console.log(binding.value)
// console.log(binding.expression)
el.style.color = binding.value
}
},
'fontsize': function(el, binding) { // 这个func等同于把代码写到了bind和update中去
el.style.fontSize = parseInt(binding.value) + 'px'; // 使用parseInt防止传入类似30px这样的值
}
}
// 使用
<h3 v-color="'pink'" v-fontsize="30">lance</h3>