Vue(三) (Vue-cli)-cnblog
Vue(三) (Vue-cli)
1. 单页面应用程序(SPA)
- 一个web网站只有唯一的html页面
2. vue-cli
- 简化了webpack创建工程化Vue项目的全过程
- 不需要自己去配置webpack,只需专心写页面
2.1 安装
- 全局包
- 代码
npm i -g @vue/cli
2.2 创建Vue项目
vue create 项目的名称





2.3 项目结构
- 
public文件夹 - ico图标
- index.html(单页面)
 
- 
src文件夹 - assert文件夹:静态资源,css,图片
- components文件夹:组件,可复用的,程序员封装的组件
- main.js:项目的入口文件,就是webpack要打包谁(打包main.js),项目运行时首先运行这个文件
- app.vue:项目的根组件:(UI结构)
 
3. vue项目的运行过程
- vue通过main.js把App.vue渲染到index.html的指定区域中
3.1 main.js 代码解析
// 导入vue框架
import Vue from 'vue'
// 导入App.vue的UI结构
import App from './App.vue'
Vue.config.productionTip = false
// new 一个vue的实例
// new Vue({
//     // render是一个函数,将App.vue中的结构替换到 #app的盒子中
//     render: h => h(App),
// }).$mount('#app')
// 等价于
new Vue({
    el: '#app',
    // render是一个函数,将App.vue中的结构替换到 #app的盒子中
    render: h => h(App),
})
- 注意点
Vue实例中的$mount()方法,作用与el属性完全一样
4. vue组件
- 
页面可复用的UI结构封装成组件 
- 
vue组件的组成部分 - template:组件模板结构(html)
- script:js行为
- style:样式
 
一个实例
- Test.vue
<!-- 组件的模板 -->
<template>
<!-- 获取data数据源 -->
    <div class="box">
        <h3>{{ username }}</h3>
    <!-- 调用方法 -->
        <button @click="changeName">修改用户名</button>
    </div>
    
</template>
<!-- 组件的js行为 -->
<script>
// 默认导出
export default ({
    // 里面的data 不能指向一个对象,需要的是一个函数
    // data数据源
    data(){
        // 通过return 来 暴露这个 {}
        return {
            username:'zhangsan'
        }
    },
    // 也可用调用方法
    methods: {
        changeName(){
            // vue文件中的this代表vue组件实例
            console.log(this);
            this.username='77999'
        }
    }
})
</script>
<!-- style样式 -->
<style>
    h3{
        color: blue;
        background-color: pink;
    }
</style>
- main.js
// 导入vue框架
import Vue from 'vue'
// 导入App.vue的UI结构
// import App from './App.vue'
// 导入测试的.vue 组件
import Test from './Test.vue'
Vue.config.productionTip = false
// new 一个vue的实例
// new Vue({
//     // render是一个函数,将App.vue中的结构替换到 #app的盒子中
//     render: h => h(App),
// }).$mount('#app')
// 等价于
new Vue({
    el: '#app',
    // render是一个函数,将App.vue中的结构替换到 #app的盒子中
    render: h => h(Test),
})
- 被替换UI结构的index页面
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
        // 这里被替换
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
- 效果图

4.2 注意点
- 在template节点中,模板只能有一个大盒子
- 正确用法
<template>
<!-- 获取data数据源 -->
    <div class="box">
        <h3>{{ username }}</h3>
    <!-- 调用方法 -->
        <button @click="changeName">修改用户名</button>
    </div>
    
</template>
- 错误用法(出现了两个根标签)
<template>
<!-- 获取data数据源 -->
    <div class="box">
        <h3>{{ username }}</h3>
    <!-- 调用方法 -->    
    </div>
<button @click="changeName">修改用户名</button>
    
</template>
4.3 style节点中启用less语法
- lang属性设置
<style lang="less">
    h3{
        color: blue;
        background-color: pink;
        
        p{
            color:pink;
        }
    }
</style>
4.4 组件的使用
- 存在多个组件的情况下,如果要使组件之间产生关系,需要以下3个步骤
- 使用import语法导入需要的组件
- 使用commponent节点注册组件
- 以标签的形式使用刚才注册的组件
 
- 图解

示例
- left组件
<template>
  <div class="left-container">
    <h3>Left 组件</h3>
  </div>
</template>
<script>
export default {}
</script>
<style lang="less">
.left-container {
  padding: 0 20px 20px;
  background-color: orange;
  min-height: 250px;
  flex: 1;
}
</style>
- right组件
<template>
  <div class="right-container">
    <h3>Right 组件</h3>
  </div>
</template>
<script>
export default {}
</script>
<style lang="less">
.right-container {
  padding: 0 20px 20px;
  background-color: lightskyblue;
  min-height: 250px;
  flex: 1;
}
</style>
- App根组件(使用了left和right组件)
<template>
  <div class="app-container">
    <h1>App 根组件</h1>
    <hr />
    <div class="box">
      <!-- 渲染 Left 组件和 Right 组件 -->
      <!-- 使用标签的格式来渲染left和right指令 -->
      <left></left>
      <right></right>
    </div>
  </div>
</template>
<script>
// 导入left组件和right组件
import left from '@/components/Left.vue'
import right from "@/components/Right.vue"
export default {
  //  注册left和right组件
  components: {
    left,
    right
  }
}
</script>
<style lang="less">
.app-container {
  padding: 1px 20px 20px;
  background-color: #efefef;
}
.box {
  display: flex;
}
</style>
- 效果图

4.5 全局组件
在main.js入口文件中,使用Vue.compoent()方法,注册全局组件
- main.js
import Vue from 'vue'
import App from './App.vue'
// 导入全局组件 Count
import Count from '@/components/Count.vue'
Vue.config.productionTip = false
// 注册全局组件
// 第一个参数 组件的注册名称
// 的二个参数  原来组件的名称
Vue.component("Mycount", Count);
new Vue({
    render: h => h(App),
}).$mount('#app')
- left使用全局组件
<template>
  <div class="left-container">
    <h3>Left 组件</h3>
    <!-- 使用全局组件 -->
    <Mycount></Mycount>
  </div>
</template>
<script>
export default {}
</script>
<style lang="less">
.left-container {
  padding: 0 20px 20px;
  background-color: orange;
  min-height: 250px;
  flex: 1;
}
</style>
4.6 组件的props
- 
自定义属性,用于提高代码的复用性 
- 
count组件使用定义自定义组件 
<!-- 初始化组件   <v  快捷键 -->
<template>
  <div>
    <h5>Count 全局组件</h5>
    <p>{{count}}</p>
    <p>{{count1}}</p>
    <button @click="count+=1">+1</button>
  </div>
</template>
<script>
export default {
    // 设置自定义属性
    props:['count1'],
    data(){
        return {
            count:0
        }
    }
}
</script>
<style lang="less">
    h5{
        background-color: pink;
        color: blue;
    }
</style>
- left组件设置自己的count1值
<template>
  <div class="left-container">
    <h3>Left 组件</h3>
    <!-- 使用全局组件 -->
    <!-- 设置自定义属性 -->
    <Mycount count1='1'></Mycount>
  </div>
</template>
- right组件也设置自己的count1值
<template>
  <div class="right-container">
    <h3>Right 组件</h3>
    <Mycount count1='2'></Mycount>
  </div>
</template>
- 效果图

4.7 配合v:bind来使用自定义属性
- 
使用者(left,right)使用count组件时,如果不使用v-bind 设置的自定义属性值为字符串 
- 
使用了v-bind时,设置的值为数字 
- 
left 
<Mycount count1='1'></Mycount>
- right
<Mycount v-bind:count1="2"></Mycount>
- 效果图


4.8 组件的props中属性是只读的
- 不要去写
- 可以将该属性的值赋给data中的某一个属性,实现可读可写
props:['count1'],
    data(){
        return {
            count:this.count1
        }
    }
4.9 设置props的默认值
- 设置count1的默认值为0
props:{
        count1:{
            default :0,
        }
    },
4.10 设置props的值类型
- 如果组件的使用者(left,right)设置的值不为设置的值类型,
- 则会报错
props:{
        count1:{
            default :0,
            // 设置自定义属性的值类型
            type:Number,
        }
    },
4.11 props的require属性
- 设置自定义属性的值为必填项,否则报错
props:{
        count1:{
            default :0,
            // 设置自定义属性的值类型
            type:Number,
            // 设置必填项属性
            required:true,
        }
    },
5. 组件之间的样式冲突问题
- 原因
默认情况下,写在vue组件中的style样式会全局生效
- 解决原理
给每一个vue组件的html标签都加上自己特定的自定义属性(data-v-xxx),然后写样式是在嵌套上属性选择器来实现精准样式设置
- 解决方案
在style节点添加scoped属性(vue根据上述原理解决样式冲突)
<style lang="less" scoped>
    h5{
        background-color: pink;
        color: blue;
    }
</style>
5.2 deep深度选择器
- 
如果在当前的vue组件的style样式中添加了scoped属性 
- 
如果当前vue组件使用了其他组件,则对其他组件样式不生效(其他组件上面没有自定义属性【data-v-xxx】) 
- 
解决方案 
使用/deep/ :代表属性选择器
- 
配合其他选择器实现样式穿透 
- 
count组件样式 
<style lang="less" scoped>
    h5{
        background-color: pink;
        color: blue;
    }
</style>
- left组件样式(left使用了count子组件)
/deep/ h5{
	// 选择器层级b
    color: red !important;
}
- 效果图

 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号